在Scala中编写Kleisli和Reader monad

时间:2016-01-12 15:14:13

标签: scala scalaz reader-monad kleisli

假设我有这样的功能:

val fooXAB: X => A => Try[B] = ...
val fooXBC: X => B => Try[C] = ...
val fooXCD: X => C => Try[D] = ...

我想将它们组合成一个新功能fooXAD: X => A => Try[D],它会依次调用fooXABfooXBCfooXCD并传递{{1}所有这些的参数。

假设我使用X并拥有scalaz的monad实例。现在我可以这样做:

scala.util.Try

有意义吗?是否有可能简化它?

1 个答案:

答案 0 :(得分:1)

所以我不认为外部功能上的Reader Monad在这里有所帮助。一旦你向你的三个XReader申请和X,你可以在结果上使用Kleisli组合(假设你有一个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)
}