flatMap如何与自定义monad一起使用

时间:2020-02-20 08:34:19

标签: scala monads

我是scala的新手,并对Monads的实现感到困惑。在下面的程序中,当执行“ a <-g(3)”时,“ a”的值为23而不是Writer,为什么?幕后发生了什么?

case class Writer(value:Int, log:String) {
  def map(f:Int=>Int): Writer = {
    Writer(f(value), log)
  }
  def flatMap(f:Int=>Writer): Writer = {
    val temp = f(value)
    Writer(temp.value, log+"...."+temp.log)
  }
}

object Test extends App {

  def f(value: Int):Writer = {
    Writer(40+value, s"f has $value")
  }

  def g(value: Int):Writer = {
    Writer(20+value, s"g has $value")
  }

  val result1 = for {
    a <- g(3)
    b <- f(a)
  } yield b

  println(result1)

  val result2 = g(3) flatMap {
    a => f(a).map(b=>b)
  }

  println(result2)
}

2 个答案:

答案 0 :(得分:2)

从scala文档for comprehensionhttps://docs.scala-lang.org/tutorials/FAQ/yield.html https://docs.scala-lang.org/tour/for-comprehensions.html

它仅是组成多个单子操作的语法糖

您的通话

for {
    a <- g(3)
    b <- f(a)
  } yield b

被贬低为:

g(3).flatMap { n =>
  f(n)
}

对g(3)的评估结果应用减糖。您可以将其视为:

writer: Writer = g(3) // evaluation of g(3)

writer.flatMap { n => // flatMap on Writer
  here n is your value which is Int
...

因此,这里的n与语法糖中的a等价

答案 1 :(得分:0)

cats库为monad提供了一个通用接口:

https://typelevel.org/cats/typeclasses/monad.html

在此文档页面中,您可以找到如何有效而正确地创建自己的monad的方法。 此外,猫还具有自己的Writer monad,用法示例:

https://medium.com/@spearsear/simple-use-of-cats-writer-monad-4a1694556112