1

次のような関数があるとします。

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

それらを構成して、 、 、および を順番fooXAD: X => A => Try[D]に呼び出しfooXAB、それらすべてに引数を渡す新しい関数 を作成したいと思います。fooXBCfooXCDX

scalazのモナドインスタンスを使用して持っているとしますscala.util.Try。今、私はこのようにすることができます:

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)  

それは理にかなっていますか?それを単純化することは可能ですか?

4

1 に答える 1

1

したがって、外部関数の Reader モナドはここでは役に立たないと思います。threee に X を適用すると、結果に対してコンポジションXReaderを使用できます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)
}
于 2016-01-12T17:03:55.747 に答える