我是函数式编程和Scala的新手,我正在查看Cats Effect框架,并试图了解IO monad的功能。到目前为止,我所理解的是,在IO块中编写代码只是对需要做什么的描述,在使用所提供的unsafe
方法显式运行之前不会发生任何事情,也是一种通过实际不运行来使执行副作用的代码透明化的方法
我试着执行下面的片段,只是想理解它的含义:
object Playground extends App {
var out = 10
var state = "paused"
def changeState(newState: String): IO[Unit] = {
state = newState
IO(println("Updated state."))
}
def x(string: String): IO[Unit] = {
out += 1
IO(println(string))
}
val tuple1 = (x("one"), x("two"))
for {
_ <- x("1")
_ <- changeState("playing")
} yield ()
println(out)
println(state)
}
结果是:
13
paused
我不明白为什么赋值state = newState
不运行,但增量和赋值表达式out += 1
运行。我是不是错过了一些关于这应该如何工作的明显内容?我真的需要一些帮助。我知道我可以使用unsafe
方法来运行它。
在您的特定示例中,我认为Scala编码的常规命令式不受IO
monad的影响——它在Scala规则下正常运行。
运行时:
for {
_ <- x("1")
_ <- changeState("playing")
} yield ()
这立即调用CCD_ 6。这与IO
monad无关;这就是CCD_ 8理解的定义。第一步是评估第一条语句,这样您就可以对其调用flatMap
正如你所观察到的;运行";一元结果,因此flatMap
的自变量,即一元延续,永远不会被调用,从而不会调用changeState
。这是特定于IO
monad的,例如,List
monad的flatMap
会立即调用该函数(除非它是空列表(。