3

假设我有一些由以下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))

为了编写fw1, fw2fw3我可能需要用Kleisli. 但是由于不是 monad Kleisli(fw1),因此无法编译。Writer[List[Int], Int]

我想我可能需要 amonad transformer来制作Writer[List[Int], Int]一个 monad,但我不知道该怎么做。所以,我的问题是:如何Kleisli(fw1)使用 monad 转换器进行编译?

4

1 回答 1

3

Writer[List[Int], ?]确实有一个 monad 实例——这只是 scalac 在没有一点帮助的情况下无法看到的情况。您可以只使用kleisliU,这就像Kleisli.apply但有一些类型推断帮助Unapply在此处和许多其他地方进行了描述):

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.applyor提供显式类型参数Kleisli.kleisli

于 2015-08-28T18:30:04.867 回答