猫效应 IO monad 是如何工作的?
How does the cats-effect IO monad really work?
我是函数式编程和 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 的影响——它 运行s 在 Scala 规则下通常会受到影响.
当你运行:
for {
_ <- x("1")
_ <- changeState("playing")
} yield ()
这会立即调用 x
。这与 IO
monad 无关; for
理解就是这样定义的。第一步是评估第一个语句,以便您可以对其调用 flatMap
。
如您所见,您永远不会“运行”一元结果,因此永远不会调用 flatMap
的参数,即一元延续,从而不会调用 changeState
.这是 IO
monad 特有的,例如,List
monad 的 flatMap
会立即调用该函数(除非它是一个空列表)。
我是函数式编程和 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 的影响——它 运行s 在 Scala 规则下通常会受到影响.
当你运行:
for {
_ <- x("1")
_ <- changeState("playing")
} yield ()
这会立即调用 x
。这与 IO
monad 无关; for
理解就是这样定义的。第一步是评估第一个语句,以便您可以对其调用 flatMap
。
如您所见,您永远不会“运行”一元结果,因此永远不会调用 flatMap
的参数,即一元延续,从而不会调用 changeState
.这是 IO
monad 特有的,例如,List
monad 的 flatMap
会立即调用该函数(除非它是一个空列表)。