下面是一个小的函数组合,所有这些函数都返回ReaderT
type FailFast[A] = Either[List[String], A]
def f1:ReaderT[FailFast, Map[String,String], Boolean] = ReaderT(_ => Right(true))
def f2:ReaderT[FailFast, Map[String,String], Boolean] = ReaderT(_ => Left(List("d")))
def f3:ReaderT[FailFast, Map[String,String], Boolean] = ReaderT(_ => Right(true))
def f4:ReaderT[FailFast, Map[String,String], Boolean] = ReaderT(_ => Right(true))
def fc:ReaderT[FailFast, Map[String,String], Boolean] =
f1.flatMap( b1 => {
if (b1)
for {
b2 <- f2
b3 <- f3
b4 <- f4
} yield b4
else ReaderT(_ => Right(true))
})如何在f1返回Reader而不是ReaderT的情况下实现fc
def f1:Reader[Map[String,String], Boolean] = Reader(_ => true)现在我必须编写Reader,这与Reader[FailFast, ...]的ReaderT[Id, ...]完全相同
发布于 2019-03-27 18:47:24
正如您所提到的,Reader[A, B]只是ReaderT[Id, A, B] (它本身只是Kleisli[Id, A, B]的一个类型别名)。
因为您使用的是cats,所以有一个名为mapK的方法,它映射到ReaderT的第一个类型参数上,您只需要提供一个FunctionK/~>实例来进行转换。所以在你的例子中,它看起来像这样:
val Id2FailFast = new (Id ~> FailFast) {
def apply[T](f: Id[T]): FailFast[T] = Right(f)
}
f1.mapK(Id2FailFast).flatMap( b1 => {
if (b1)
for {
b2 <- f2
b3 <- f3
b4 <- f4
} yield b4
else ReaderT(_ => Right(true))
})可能还有其他一些重构可以进一步清理它,比如使用EitherT,但由于它看起来有点做作的例子,我将把它留给读者作为练习。
https://stackoverflow.com/questions/55375125
复制相似问题