For-comprehension for io monad 什么都不打印
For-comprehension for io monad prints nothing
我正在试验 IO monad,这是我写的:
val io: IO[String] = "asdfasdf".pure[IO]
val i: IO[Unit] = for{
str <- io
} yield {
println(str).pure[IO]
}
i.unsafePerformIO() // Performing io ops
代码没有输出。以下代码依次按预期工作:
val io: IO[Unit] = "asdfasdf".pure[IO].flatMap(println(_).pure[IO])
io.unsafePerformIO() //prints asdfasdf
为什么?有什么区别?
您刚刚对 scala 遇到了一个巨大的烦恼:推断 Unit
for{
str <- io
} yield {
println(str).pure[IO]
}
这个表达式是一个 IO[IO[Unit]]
,但是因为你告诉 scala(通过值的类型)你想要一个 IO[Unit]
,它基本上将表达式转换为如下:
for{
str <- io
} yield {
println(str).pure[IO] // <-- this IO action is basically thrown away
() // <-- inserted a Unit return
}
旁白... 请注意,此转换似乎是可能的,因为 IO[A]
在 A
中是不变的。如果将 IList
替换为 IO
而不是 List
(其类型参数是协变的),也会发生同样的事情,在这种情况下片段不会编译
返回答案...
相反,你应该写成:
for {
str <- io
_ <- println(str).pure[IO]
}
yield ()
更多旁白...
我个人只使用 expr.pure[IO]
其中 expr
是一个纯表达式,我使用 IO(expr)
其中 expr
是副作用,所以我更喜欢:
for {
str <- io
_ <- IO(println(str))
}
yield ()
最后,请注意这等同于:
io >>= IO.putStrLn
我正在试验 IO monad,这是我写的:
val io: IO[String] = "asdfasdf".pure[IO]
val i: IO[Unit] = for{
str <- io
} yield {
println(str).pure[IO]
}
i.unsafePerformIO() // Performing io ops
代码没有输出。以下代码依次按预期工作:
val io: IO[Unit] = "asdfasdf".pure[IO].flatMap(println(_).pure[IO])
io.unsafePerformIO() //prints asdfasdf
为什么?有什么区别?
您刚刚对 scala 遇到了一个巨大的烦恼:推断 Unit
for{
str <- io
} yield {
println(str).pure[IO]
}
这个表达式是一个 IO[IO[Unit]]
,但是因为你告诉 scala(通过值的类型)你想要一个 IO[Unit]
,它基本上将表达式转换为如下:
for{
str <- io
} yield {
println(str).pure[IO] // <-- this IO action is basically thrown away
() // <-- inserted a Unit return
}
旁白... 请注意,此转换似乎是可能的,因为 IO[A]
在 A
中是不变的。如果将 IList
替换为 IO
而不是 List
(其类型参数是协变的),也会发生同样的事情,在这种情况下片段不会编译
返回答案...
相反,你应该写成:
for {
str <- io
_ <- println(str).pure[IO]
}
yield ()
更多旁白...
我个人只使用 expr.pure[IO]
其中 expr
是一个纯表达式,我使用 IO(expr)
其中 expr
是副作用,所以我更喜欢:
for {
str <- io
_ <- IO(println(str))
}
yield ()
最后,请注意这等同于:
io >>= IO.putStrLn