这在分配给下划线时如何理解构建状态?

How does this for comprehension build state while assigning to underscore?

背景
val forExpression(下)returns 一个 StateT monad,它将初始状态作为参数,将 2 和 3 添加到状态,然后将其乘以 10。

问题
为什么add(2)add(3)函数在这个StateT实例是[=43=时执行] 在这两个函数似乎通过将其分配给下划线来获得结果后 "thrown away"?

示例
如果您评估 forExpression 的起始状态为 IntState(1),为什么它 return IntState(60) 而不是 IntState(10)?

下面有一个最小的代码片段,或者您可以查看完整的源代码on github

这段代码是在阅读 Alvin Alexander 的 "Functional Programming Simplified" 时遇到的。

  case class IntState(i: Int)

  def add(i: Int) = StateT[IO, IntState, Int] { oldState =>
    val newValue = i + oldState.i
    val newState = oldState.copy(i = newValue)
    IO((newState, newValue))
  }

  def multiply(i: Int) = StateT[IO, IntState, Int] { oldState =>
    val newValue = i * oldState.i
    val newState = oldState.copy(i = newValue)
    IO((newState, newValue))
  }

  val forExpression: StateT[IO, IntState, Int] = for {
    _ <- add(2)
    _ <- add(3)
    x <- multiply(10)
  } yield x

简单的高级解释:StateT 计算具有独立的状态和结果(例如,代码中 IO((newState, newValue)) 中的 newStatenewValue)。出现在<-左边的是newValue部分,只有在_ <- ...中被忽略了。 newState 的操作是隐式的,不会被丢弃。

对于低级,你可以:

  1. 将for-comprehension翻译成flatMap.

  2. 扩展StateTflatMap的定义。

  3. 看看结果函数中的状态会发生什么。