首页 > 解决方案 > 在分配给下划线时,这对于理解如何构建状态?

问题描述

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

问题
为什么在这两个函数的结果似乎通过将其分配给下划线“丢弃”之后运行此实例时执行add(2)and函数?add(3)StateT

例如
,如果您评估forExpression的初始状态为IntState(1),为什么它返回IntState(60)而不是IntState(10)

下面有一个最小的代码片段,或者您可以在 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

标签: scalafunctional-programmingfor-comprehension

解决方案


简单的高级解释:StateT计算具有单独的状态和结果(例如newStatenewValueIO((newState, newValue))您的代码中)。左边出现的<-newValue零件,只有它在 中被忽略_ <- ...。的操作newState是隐含的,不会被丢弃。

对于低级,您可以:

  1. 将理解翻译成flatMap

  2. 扩展StateT's的定义flatMap

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


推荐阅读