我正在尝试解决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))
}
答案 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._
WriterString
是Writer
的类型别名,可以转换为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的参数分配给某些东西,但是您可能决定不使用它)。