在 Scala 中编写 Kleisli 和 Reader monad
Composing Kleisli and Reader monad in Scala
假设我有这样的函数:
val fooXAB: X => A => Try[B] = ...
val fooXBC: X => B => Try[C] = ...
val fooXCD: X => C => Try[D] = ...
我想将它们组合成一个新函数 fooXAD: X => A => Try[D]
,它依次调用 fooXAB
、fooXBC
和 fooXCD
并传递 X
所有参数。
假设我使用 scalaz
并且有一个 scala.util.Try
的 monad 实例。现在我可以这样做了:
type AB = Kleisli[Try, A, B]
type BC = Kleilsi[Try, B, C]
type CD = Kleisli[Try, C, D]
type XReader[T] = Reader[X, T]
val fooXAB: XReader[AB] = ...
val fooXBC: XReader[BC] = ...
val fooXCD: XReader[CD] = ...
val fooXAC: XReader[AC] =
for {
ab <- fooXAB
bc <- fooXBC
cd <- fooXCD
} yield (ab andThen bc andThen cd)
有道理吗?是否可以简化它?
所以我认为外部函数上的 Reader Monad 在这里没有帮助。一旦你将 X 应用到三个 XReader
s,你就可以对结果使用 Kleisli
组合(假设你有一个用于 Try 的 Monad 实例)。这是您以这种方式修改的示例,它为我编译:
import scala.util.{Try,Success}
import scalaz._
import Scalaz._
object A
object B
object C
object D
trait X
object Main {
implicit val pretendTryIsAMonad: Monad[Try] = new Monad[Try] {
def point[A](a: => A): Try[A] = Success(a)
def bind[A,B](fa: Try[A])(f: A => Try[B]): Try[B] = fa flatMap f
}
type AB = Kleisli[Try, A.type, B.type]
type BC = Kleisli[Try, B.type, C.type]
type CD = Kleisli[Try, C.type, D.type]
type AD = Kleisli[Try, A.type, D.type]
type XReader[T] = X => T
val fooXAB: XReader[AB] = (x: X) => Kleisli((a: A.type) => Success(B))
val fooXBC: XReader[BC] = (x: X) => Kleisli((b: B.type) => Success(C))
val fooXCD: XReader[CD] = (x: X) => Kleisli((c: C.type) => Success(D))
val fooXAD: XReader[AD] = (x: X) =>
fooXAB(x) >=> fooXBC(x) >=> fooXCD(x)
}
假设我有这样的函数:
val fooXAB: X => A => Try[B] = ...
val fooXBC: X => B => Try[C] = ...
val fooXCD: X => C => Try[D] = ...
我想将它们组合成一个新函数 fooXAD: X => A => Try[D]
,它依次调用 fooXAB
、fooXBC
和 fooXCD
并传递 X
所有参数。
假设我使用 scalaz
并且有一个 scala.util.Try
的 monad 实例。现在我可以这样做了:
type AB = Kleisli[Try, A, B]
type BC = Kleilsi[Try, B, C]
type CD = Kleisli[Try, C, D]
type XReader[T] = Reader[X, T]
val fooXAB: XReader[AB] = ...
val fooXBC: XReader[BC] = ...
val fooXCD: XReader[CD] = ...
val fooXAC: XReader[AC] =
for {
ab <- fooXAB
bc <- fooXBC
cd <- fooXCD
} yield (ab andThen bc andThen cd)
有道理吗?是否可以简化它?
所以我认为外部函数上的 Reader Monad 在这里没有帮助。一旦你将 X 应用到三个 XReader
s,你就可以对结果使用 Kleisli
组合(假设你有一个用于 Try 的 Monad 实例)。这是您以这种方式修改的示例,它为我编译:
import scala.util.{Try,Success}
import scalaz._
import Scalaz._
object A
object B
object C
object D
trait X
object Main {
implicit val pretendTryIsAMonad: Monad[Try] = new Monad[Try] {
def point[A](a: => A): Try[A] = Success(a)
def bind[A,B](fa: Try[A])(f: A => Try[B]): Try[B] = fa flatMap f
}
type AB = Kleisli[Try, A.type, B.type]
type BC = Kleisli[Try, B.type, C.type]
type CD = Kleisli[Try, C.type, D.type]
type AD = Kleisli[Try, A.type, D.type]
type XReader[T] = X => T
val fooXAB: XReader[AB] = (x: X) => Kleisli((a: A.type) => Success(B))
val fooXBC: XReader[BC] = (x: X) => Kleisli((b: B.type) => Success(C))
val fooXCD: XReader[CD] = (x: X) => Kleisli((c: C.type) => Success(D))
val fooXAD: XReader[AD] = (x: X) =>
fooXAB(x) >=> fooXBC(x) >=> fooXCD(x)
}