2015-08-28 39 views
3

假设我有andThen由几个功能Int => Int如何编写返回Writer的函数[List [Int],Int]?

val f1: Int => Int = _ + 1 
val f2: Int => Int = _ + 2 
val f3: Int => Int = _ + 3 

val f = f1 andThen f2 andThen f3 

现在我还需要返回中间结果。所以我可以将所有这些函数转换为Int => (List[Int], Int),其中列表包含参数。

我大概可以使用scalazWriter[List[Int], Int]代表对(List[Int], Int)

val fw1: Int => Writer[List[Int], Int] = x => f1(x).set(List(x)) 
val fw2: Int => Writer[List[Int], Int] = x => f2(x).set(List(x)) 
val fw3: Int => Writer[List[Int], Int] = x => f3(x).set(List(x)) 

为了撰写fw1fw2fw3我可能需要Kleisli来包装它们。但是Kleisli(fw1)不能编译,因为Writer[List[Int], Int]不是monad。

我想我可能需要一个monad transformer来使Writer[List[Int], Int] monad,但我不知道如何做到这一点。所以,我的问题是:如何使用monad变压器编译Kleisli(fw1)

回答

3

Writer[List[Int], ?]确实有monad实例 - 这只是scalac无法在没有一点帮助的情况下看到的情况。你可以只用kleisliU,这就好比Kleisli.apply但从Unapply一些类型推断的帮助(这是描述here和其他一些地方):

import scalaz._, Scalaz._, Kleisli.kleisliU 

val f1: Int => Int = _ + 1 
val f2: Int => Int = _ + 2 
val f3: Int => Int = _ + 3 

val fw1: Int => Writer[List[Int], Int] = x => f1(x).set(List(x)) 
val fw2: Int => Writer[List[Int], Int] = x => f2(x).set(List(x)) 
val fw3: Int => Writer[List[Int], Int] = x => f3(x).set(List(x)) 

val f = kleisliU(fw1) andThen kleisliU(fw2) andThen kleisliU(fw1) 

然后:

scala> f.run(10) 
res0: scalaz.WriterT[[+X]X,List[Int],Int] = WriterT((List(10, 11, 13),14)) 

你也可以为Kleisli.applyKleisli.kleisli提供显式类型参数。

+0

谢谢你的回答,并提醒我有关'Unapppy'。也许我会尝试这次饶舌。 – Michael