下面的理解如何工作?
How does below for comprehension work?
我正在尝试解决 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))
}
如果您为了理解而脱糖(例如使用 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
returns 具有 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
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
结果,则为 foreach),它之前的所有操作 - 转换为 flatMap
。操作是嵌套的(next <-
表示下一个嵌套操作)。
同样 if
s 转换为 withFilter
。
_
表示您忽略了该值(您必须将 flatMap/map 的参数分配给某些东西,但您可能决定不使用它)。
我正在尝试解决 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))
}
如果您为了理解而脱糖(例如使用 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
returns 具有 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
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
结果,则为 foreach),它之前的所有操作 - 转换为 flatMap
。操作是嵌套的(next <-
表示下一个嵌套操作)。
同样 if
s 转换为 withFilter
。
_
表示您忽略了该值(您必须将 flatMap/map 的参数分配给某些东西,但您可能决定不使用它)。