我正在使用此代码:
case class State[S, +A](run: S => (A, S)) {
...
def flatMap[B](f: A => State[S, B]): State[S, B] = State(s => {
val (a, s1) = run(s)
f(a).run(s1)
})
...
}
这是从FP in Scala的§6开始处理纯粹功能状态的抽象。 run
是一个函数参数,它接受一个状态并发出一个值的元组和一个新状态。
我的问题围绕本节中的s =>
语法:
... B] = State(s => { ...
这似乎是使用State
'构造函数'(即apply
)来构建一个新的State对象。但s
代表什么?它是一个'匿名'状态,代表任何国家实例吗?如果是这样,它与this
有什么不同?或者s对应于run
的输入参数,即S
来自:
... (run: S => ....
为什么我要使用构造函数进行函数定义?请注意,flatMap定义的最后一个符号是)
而不是}
,即关闭State
应用构造函数。
此方案与标准
略有不同case class Person(name: String)
场景,所以我想我会问......
答案 0 :(得分:10)
您的第二个假设是正确的,s
对应于run
函数的输入参数,即S
,它表示通过链的实际状态。所以s => {...}
只是类型S => (A, S)
的lambda定义。 Scala中的Lambda和函数是first-class citizens(值),因此您可以将它们作为参数传递给另一个类型(包括一些monad)。
此处生成新原始状态S
(以及新结果A
)的函数被包装(请参阅return操作)到monad状态,该状态实现为case类。我们需要它来定义flatMap
操作(参见bind)monad。
为了使传递函数更清楚地作为参数,可以将代码重写为:
case class State[S, +A](run: S => (A, S)) {
def flatMap[B](f: A => State[S, B]): State[S, B] = {
def newState(s: S) = {
val (a, s1) = run(s)
f(a).run(s1)
}
State(newState _)
}
}
所以,根据monad definition:
State[S, +A]
是一个类型构造函数,它接受两种普通类型(S
和协变A
)并返回monadic类型State
State.apply(run: S => (A, S))
函数接受一个普通函数并返回(提升)monadic容器State
,因此它是一个" return" monad的运营商State.flatMap[B](f: A => State[S, B]): State[S, B]
对应于" bind"操作 案例类仅用于显式"返回"函数(apply
)而不是new
运算符。