2016-01-12 9 views
1

Предположим, у меня есть такие функции, как это:Сочинение Клейсли и чтения монада в Scala

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

Я хотел бы, чтобы составить их, чтобы сделать новую функцию fooXAD: X => A => Try[D], которая вызывает fooXABfooXBC, и fooXCD последовательно и передать X аргумент для всех из них.

Предположим, я использую 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) 

Имеет ли смысл? Можно ли это упростить?

ответ

1

Так что я не думаю, что Reader Monad на внешней функции помогает здесь. после того, как вы примените и X к вашему трюку XReader, вы можете использовать композицию по результатам (если у вас есть экземпляр Monad для Try). Вот ваш пример, переработанный таким образом, и он компилируется для меня:

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) 
} 
+0

Возможно, вы правы ... Теперь мне интересно, когда «читатель» монада _does_ действительно помогает. – Michael