scala - 理解 Scala 中的 IO-monad

标签 scala io scalaz

我的 Scala 中有以下内容

import scalaz.effect.IO
val i: Iterator[IO[List[String]]] = null

val ii: Iterator[IO[List[String]]] = for{ //This does not compile
  io <- i;
  lst <- io
} yield lst

为什么?怎么了?

我预计 iii 完全相同。但它拒绝编译:

Error:(12, 11) type mismatch;
 found   : scalaz.effect.IO[List[String]]
 required: scala.collection.GenTraversableOnce[scalaz.effect.IO[List[String]]]
      lst <- io

最佳答案

flatMap在 Scala 中

回想一下,for-comprehensions 只是对 flatMap 的加糖调用:

for {
  a <- expr  //expr must return M[A] such that M has a 
             //flatMap method: flatMap[B](f: A => N[B]) for some N

  b <- f(a)  //f(a) must be an N[B]
  ...

您的问题

这是Iterator.flatMap的签名

def flatMap[B](f: A => GenTraversableOnce[B]): Iterator[B]

但是您试图提供一个返回 IO[B] 的函数:

lst <- io //You cannot just have `io` on the right here

因此编译错误。

flatMap再次在 Scala 中

Scala 的 flatMap <~> for-comprehension应用于集合类型(和 Option)的转换(在我看来)令人困惑,因为它们允许您在不同类型的 Monad 之间切换(例如 List/Option/Set 等)。例如,x 的类型是什么?在这里?

val x = 
  for  {
    i <- List(1, 2, 3)
    j <- Option(i + 1)
    k <- Stream(i, j)
  } yield k

scalaz 中的单子(monad)

仔细看看 scalaz.MonadflatMap :

trait Monad[M[_]] {
  def flatMap[A, B](ma: M[A])(f: A => M[B]): M[B]
}

M 的类型总是固定的。也就是说,在这个理解中:

lazy val ma: M[A] = ???
for (a <- ma; b <- f(a)) yield b

函数的结果类型f 必须在 M[B] 中对于一些 B 。虽然有时这可能有点烦人,但它具有完全可预测 的优势。你永远不会对 你的 for comprehension 是什么 monad 感到困惑

回到问题

你想要什么并不明显,但这里有一些建议:

i.toStream.sequence.map(flatten) //IO[Stream[String]]

关于scala - 理解 Scala 中的 IO-monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47439124/

相关文章:

scala - 更改 Play IsAuthenticated 中的身份验证方法

linux - 调整顺序磁盘读取以提高性能

java - 如何从 .t​​xt 文件读取二维数组?

scala - 如何修复到 Applicative 的隐式转换?

scala - 有没有办法通过命令行为 sbt 指定备用位置以查找构建配置?

scala - 如何运行 Monix 的 parSequenceUnordered 并处理每个任务的结果?

scala - 在 scala 中基于鸭子类型定义泛型类型?

arrays - 为什么数组的元素在乘以 1/2 或 1/3 时被格式化为零?

scala - 对一系列类型的抽象

scala - 如果是 scala.Ordering,这个 case 有什么用?