【问题标题】:How to compose functions that return Writer[List[Int], Int]?如何编写返回 Writer[List[Int], Int] 的函数?
【发布时间】:2015-08-28 16:07:35
【问题描述】:

假设我有几个函数Int => IntandThen 组成:

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

我大概可以使用scalaz中的Writer[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] 成为一个单子,但我不知道该怎么做。所以,我的问题是:如何使 Kleisli(fw1) 用 monad 转换器编译?

【问题讨论】:

    标签: scala scalaz monad-transformers writer-monad


    【解决方案1】:

    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 提供显式类型参数。

    【讨论】:

    • 感谢您的回答并提醒我Unapppy。也许这次我会试着去摸它。
    猜你喜欢
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多