scala - 在分配给下划线时,这对于理解如何构建状态?
问题描述
背景
val forExpression
(如下)返回一个StateT
monad,它以初始状态为参数,将 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
解决方案
简单的高级解释:StateT
计算具有单独的状态和结果(例如newState
,newValue
在IO((newState, newValue))
您的代码中)。左边出现的<-
是newValue
零件,只有它在 中被忽略_ <- ...
。的操作newState
是隐含的,不会被丢弃。
对于低级,您可以:
将理解翻译成
flatMap
。扩展
StateT
's的定义flatMap
。看看结果函数中的状态会发生什么。
推荐阅读
- java - 如何使用 apache camel 根据内容大小添加另一个 xml 标签
- python - 将 MacBook 更新到 macOS Catalina 后出现 Anaconda 问题
- python - Finding smallest entry in a dictionary, getting last key-value pair instead
- java - 如何使 Java 服务器从变量而不是控制台输入中读取?
- flutter - 使用 SelectableText (Flutter) 缺少 TextSpan 的 onTap 回调
- linux - 从 Windows 客户端连接到 Ubuntu 18.04,安装的 Samba 无法正常工作
- python - 我应该从列中删除重复项(嵌入层输入)吗?
- php - Laravel - 如何使用 Query Builder 或 Eloquent 添加 JOIN 和 CASE-WHEN?
- c# - 包含字符串的结构与包含字符串的类的性能
- javascript - 如何在表格移出视图(高度)时动态拆分表格 - CSS,JS