对于io monad的理解不打印

时间:2017-11-21 17:08:18

标签: scala io scalaz

我正在试验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

为什么呢?有什么区别?

1 个答案:

答案 0 :(得分:4)

你刚刚对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