如何编写返回Writer [List [Int],Int]的函数?

时间:2015-08-28 16:07:36

标签: scala scalaz monad-transformers writer-monad

假设我有一些由Int => Int组成的函数andThen

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),其中列表包含参数。

我可以使用Writer[List[Int], Int] scalaz代表(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)

1 个答案:

答案 0 :(得分: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提供明确的类型参数。