下面的理解力如何工作?

时间:2018-07-04 12:00:49

标签: scala functional-programming monads

我正在尝试解决https://github.com/dehun/learn-fp/blob/master/src/test/scala/learnfp/monad/WriterTest.scala中的练习。目前,我无法理解以下代码的工作原理,尤其是行号20、22和24。WriterString没有map方法。另外,_的用途是什么?

"writer monad" should {
    "work" in {
      val s : Int = 3
      type WriterString[A] = Writer[List[String], A];
      {
        for {
          x <- 1.pure[WriterString]
          _ <- tell(List("een"))
          y <- 2.pure[WriterString]
          _ <- tell(List("twee"))
          z <- 3.pure[WriterString]
          _ <- tell(List("drie"))
      } yield (x, y, z) }.run() shouldBe (List("een", "twee", "drie"), (1, 2, 3))
    }

2 个答案:

答案 0 :(得分:1)

如果您对理解力不满意(例如,使用intellij或手动) 你会得到

  {
    1.pure[WriterString]
      .flatMap(
        x =>
          tell(List("een")).flatMap {
            case _ =>
              2.pure[WriterString]
                .flatMap(
                  y =>
                    tell(List("twee")).flatMap {
                      case _ =>
                        3.pure[WriterString]
                          .flatMap(z => tell(List("drie")).map { case _ => (x, y, z) })
                  }
                )
        }
      )
  }.run()

在case子句中注意_(下划线),它们基本上意味着我们不在乎该值。特别是在这里,我们不在乎,因为tell返回类型值为Unit的Writer。

def tell[W](m:W)(implicit monoid:Monoid[W]):Writer[W, Unit] = ???

tell来自导入import learnfp.functor.Writer._

WriterStringWriter的类型别名,可以转换为FunctorOps(可能具有map方法)-https://github.com/dehun/learn-fp/blob/master/src/main/scala/learnfp/functor/Writer.scala#L16

答案 1 :(得分:1)

for {
  a <- A
  b <- B
  c <- C
} yield (a,b,c)

翻译为

A.flatMap { a =>
  B.flatMap { b =>
     C.map { c => (a,b,c) }
  }
}

最后一个操作将转换为map(如果不对结果进行yield,则会转换为{{1}),之前的所有操作都将转换为flatMap。操作是嵌套的(下一个<-表示下一个嵌套操作)。

类似地,if转换为withFilter

_意味着您忽略了该值(您必须将flatMap / map的参数分配给某些东西,但是您可能决定不使用它)。