如何组合 Kleisli[M, A, C] 和 Kleisli[M, B, C]
How to combine Kleisli[M, A, C] and Kleisli[M, B, C]
我遵循优秀书籍 Reactive Domain Modeling 的设计,我需要将 Kleisli
与不同类型混合使用:
object CombinedKleisli {
type User = String
type Project = String
trait UserRepo
trait ProjectRepo
trait UserService {
def findByUserId : Kleisli[Future, UserRepo, User]
}
trait ProjectService {
def findProjectById : Kleisli[Future, ProjectRepo, Project]
}
trait ComposedService extends UserService with ProjectService {
for {
user <- findByUserId
project <- findProjectById
} yield (user, project)
}
}
由于类型不一致,我得到以下编译错误
Error:(28, 15) type mismatch;
found : scalaz.Kleisli[scala.concurrent.Future,domain.service.ServiceTest.ProjectRepo,(domain.service.ServiceTest.User, domain.service.ServiceTest.Project)]
(which expands to) scalaz.Kleisli[scala.concurrent.Future,domain.service.ServiceTest.ProjectRepo,(String, String)]
required: scalaz.Kleisli[scala.concurrent.Future,domain.service.ServiceTest.UserRepo,?]
project <- findProjectById
^
解决这个问题的最佳方法是什么,创建一个
trait Context {
def userRepo
def projectRepo
}
并用它污染 UserService
和 ProjectService
?
您需要想出一些方法将输入类型组合成一个类型。实现此目的的一种方法是继承——您将拥有一个类型 UserRepo with ProjectRepo
,它是 UserRepo
和 ProjectRepo
的子类。另一种方法是组合,你有一个元组 (UserRepo, ProjectRepo)
.
在这两种情况下,您通常会使用 local
到 "expand" 每个箭头的输入类型,以便您可以在 for
-comprehension 中组合它们:
for {
user <- findByUserId.local[(UserRepo, ProjectRepo)](_._1)
project <- findProjectById.local[(UserRepo, ProjectRepo)](_._2)
} yield (user, project)
这里的(UserRepo, ProjectRepo)
类型参数参数指定了新的输入类型,值参数(例如_._1
)指定了如何从新的输入类型得到原始箭头的输入类型。
我遵循优秀书籍 Reactive Domain Modeling 的设计,我需要将 Kleisli
与不同类型混合使用:
object CombinedKleisli {
type User = String
type Project = String
trait UserRepo
trait ProjectRepo
trait UserService {
def findByUserId : Kleisli[Future, UserRepo, User]
}
trait ProjectService {
def findProjectById : Kleisli[Future, ProjectRepo, Project]
}
trait ComposedService extends UserService with ProjectService {
for {
user <- findByUserId
project <- findProjectById
} yield (user, project)
}
}
由于类型不一致,我得到以下编译错误
Error:(28, 15) type mismatch;
found : scalaz.Kleisli[scala.concurrent.Future,domain.service.ServiceTest.ProjectRepo,(domain.service.ServiceTest.User, domain.service.ServiceTest.Project)]
(which expands to) scalaz.Kleisli[scala.concurrent.Future,domain.service.ServiceTest.ProjectRepo,(String, String)]
required: scalaz.Kleisli[scala.concurrent.Future,domain.service.ServiceTest.UserRepo,?]
project <- findProjectById
^
解决这个问题的最佳方法是什么,创建一个
trait Context {
def userRepo
def projectRepo
}
并用它污染 UserService
和 ProjectService
?
您需要想出一些方法将输入类型组合成一个类型。实现此目的的一种方法是继承——您将拥有一个类型 UserRepo with ProjectRepo
,它是 UserRepo
和 ProjectRepo
的子类。另一种方法是组合,你有一个元组 (UserRepo, ProjectRepo)
.
在这两种情况下,您通常会使用 local
到 "expand" 每个箭头的输入类型,以便您可以在 for
-comprehension 中组合它们:
for {
user <- findByUserId.local[(UserRepo, ProjectRepo)](_._1)
project <- findProjectById.local[(UserRepo, ProjectRepo)](_._2)
} yield (user, project)
这里的(UserRepo, ProjectRepo)
类型参数参数指定了新的输入类型,值参数(例如_._1
)指定了如何从新的输入类型得到原始箭头的输入类型。