gpt4 book ai didi

scala - flatMap 和 For-Comprehension with IO Monad

转载 作者:行者123 更新时间:2023-12-04 04:42:28 25 4
gpt4 key购买 nike

查看来自 Functional Programming in Scala 的 IO Monad 示例:

def ReadLine: IO[String] = IO { readLine }
def PrintLine(msg: String): IO[Unit] = IO { println(msg) }

def converter: IO[Unit] = for {
_ <- PrintLine("enter a temperature in degrees fahrenheit")
d <- ReadLine.map(_.toDouble)
_ <- PrintLine((d + 32).toString)
} yield ()

我决定用 flatMap 重写 converter

def converterFlatMap: IO[Unit] = PrintLine("enter a temperate in degrees F").
flatMap(x => ReadLine.map(_.toDouble)).
flatMap(y => PrintLine((y + 32).toString))

当我将最后一个 flatMap 替换为 map 时,我没有看到控制台打印出 readLine 的结果。

使用flatMap:

enter a temperate in degrees 
37.0

使用 map :

以度数输入温度

为什么?另外,签名 (IO[Unit]) 与 mapflatMap 如何保持相同?

这是本书中的IO monad。

  sealed trait IO[A] { self =>
def run: A
def map[B](f: A => B): IO[B] =
new IO[B] { def run = f(self.run) }
def flatMap[B](f: A => IO[B]): IO[B] =
new IO[B] { def run = f(self.run).run }
}

最佳答案

我认为在第二种情况下,Scala 会将 IO[IO[Unit]] 转换为 IO[Unit]。尝试在 scala 控制台中运行这两种变体,并且不要为 def converterFlatMap: IO[Unit] 指定类型,您会看到不同之处。

至于为什么map不行,从IO的定义中就很清楚了:当你映射 IO[IO[T]] 时,内部映射将只在外部 IO 上调用 run,结果将是 IO[IO[T]],因此只会执行前两个 PrintLineReadLine

flatMap 也会执行内部 IO,结果会是 IO[T],其中 T 是内部 A 的类型参数 IO,所以这三个语句都会被执行。

P.S.:我认为您错误地扩展了理解。根据 rules ,您编写的 for 循环应扩展为:

PrintLine("enter a temperate in degrees F").flatMap { case _ =>
ReadLine.map(_.toDouble).flatMap { case d =>
PrintLine((d + 32).toString).map { case _ => ()}
}
}

请注意,在此版本中,平面 map / map 是嵌套的。

P.P.S: 事实上最后的 for 语句也应该是 flatMap,而不是 map。如果我们假设 scala 有一个“返回”运算符,将值放入 monadic 上下文中,
(例如 return(3) 将创建什么都不做的 IO[Int] 并且它的函数 run 返回 3。),
然后我们可以将 for (x <- a; y <- b) yield y 重写为
a.flatMap(x => b.flatMap( y => return(y)))
但是因为 b.flatMap( y => return(y)) 的工作方式与 b.map(y => y) 完全相同,所以 scala 中用于理解的最后一条语句被扩展到 map 中。

关于scala - flatMap 和 For-Comprehension with IO Monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21800661/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com