我阅读了State Monad的定义,如下所示,其中包括flatMap的定义。我很清楚flatMap的字面定义,但是典型的用例是什么?
trait State[S,A]{
def run (initial:S):(S,A)
def flatMap[B] (f:A=>State[S,B]):State[S,B] =
State{ s =>
val (s1, a) = run(s)
f(a).run(s1)
}
}
object State{
def apply[S,A](f:S => (S,A)):State[S,A] =
new State[S,A] {
def run(initial:S): (S,A) = f(initial)
}
}
答案 0 :(得分:2)
此引用摘自wikibooks中有关Haskell中的状态monad的信息。
如果您以前使用任何其他语言编程,则可能编写了一些“保持状态”的函数。对于那些不熟悉该概念的人来说,状态是一个或多个执行某些计算所需的变量,但不在相关函数的参数之列。像C ++这样的面向对象的语言大量使用状态变量(以类和对象内的成员变量的形式)。另一方面,像C这样的过程语言通常使用在当前作用域之外声明的全局变量来跟踪状态。
但是,在Haskell中,此类技术并不是那么容易应用。这样做将需要可变的变量,这将意味着函数将具有隐藏的依赖关系,这与Haskell的函数纯度不符。幸运的是,通常可以以功能上纯净的方式跟踪状态。为此,我们将状态信息从一个函数传递到另一个函数,从而使隐藏的依赖关系更加明确。
基本上,它的目的是编写操纵状态的纯函数程序,让API计算下一个状态,而不是实际改变任何东西。
状态monad的最常见示例是:
您还可以检查cats page for the state monad
注意:还有一个更复杂的状态monad,称为IndexedState monad,它基本上为您提供了更改状态的选项。
答案 1 :(得分:2)
根据猫State
单子documentation
通过
中flatMap
上的State[S, A]
方法,您可以使用一个State
的结果 在随后的State
这意味着我们可以像这样在理解中很好地排列状态转换
val createRobot: State[Seed, Robot] =
for {
id <- nextLong
sentient <- nextBoolean
isCatherine <- nextBoolean
name = if (isCatherine) "Catherine" else "Carlos"
isReplicant <- nextBoolean
model = if (isReplicant) "replicant" else "borg"
} yield Robot(id, sentient, name, model)
通常,flatMap
的目的是链接单子计算,因此无论我们拥有什么单子,我们都可以将其包含在理解范围之内。