简体   繁体   English

猫效应 IO 单子如何真正起作用?

[英]How does the cats-effect IO monad really work?

I'm new to functional programming and Scala, and I was checking out the Cats Effect framework and trying to understand what the IO monad does.我是函数式编程和 Scala 的新手,我正在检查 Cats Effect 框架并试图了解 IO monad 的作用。 So far what I've understood is that writing code in the IO block is just a description of what needs to be done and nothing happens until you explicitly run using the unsafe methods provided, and also a way to make code that performs side-effects referentially transparent by actually not running it.到目前为止,我所理解的是,在 IO 块中编写代码只是对需要做的事情的描述,在您使用提供的unsafe方法显式运行之前什么都不会发生,也是一种制作执行副作用的代码的方法通过实际不运行它来实现引用透明。

I tried executing the snippet below just to try to understand what it means:我尝试执行下面的代码片段只是为了理解它的含义:

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)
}

And the output was: output 是:

13
paused

I don't understand why the assignment state = newState does not run, but the increment and assign expression out += 1 run.我不明白为什么赋值state = newState没有运行,但是增量和赋值表达式out += 1运行。 Am I missing something obvious on how this is supposed to work?我是否遗漏了一些关于这应该如何工作的明显内容? I could really use some help.我真的可以使用一些帮助。 I understand that I can get this to run using the unsafe methods.我知道我可以使用unsafe的方法来运行它。

In your particular example, I think what is going on is that regular imperative Scala coded is unaffected by the IO monad--it runs when it normally would under the rules of Scala.在您的特定示例中,我认为正在发生的事情是常规的命令式 Scala 编码不受IO monad 的影响 - 它在 Scala 的规则下正常运行。

When you run:当你运行时:

for {
  _ <- x("1")
  _ <- changeState("playing")
} yield ()

this immediately calls x .这立即调用x That has nothing to do with the IO monad;这与IO monad 无关; it's just how for comprehensions are defined.这就是定义理解for方式。 The first step is to evaluate the first statement so you can call flatMap on it.第一步是评估第一个语句,以便您可以在其上调用flatMap

As you observe, you never "run" the monadic result, so the argument to flatMap , the monadic continuation, is never invoked, resulting in no call to changeState .正如您所观察到的,您从不“运行”一元结果,因此从不调用flatMap的参数(一元延续),从而不会调用changeState This is specific to the IO monad, as, eg, the List monad's flatMap would have immediately invoked the function (unless it were an empty list).这是特定于IO monad,例如, List monad 的flatMap会立即调用 function(除非它是一个空列表)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM