我想以功能性方式表示自我修改功能,这使我考虑了状态monad。来自“Scala中的函数编程”一书中的版本本质上是函数S =>的案例类包装器。 (R,S)其中S是状态,R是结果。例如,它适用于此随机数生成器,如下所示:
trait RNG {
def nextInt : Int
}
case State[S,R]( run : S => (R,S) ) { /* other details omitted */ }
type Rand[R] = State[RNG,R] // `random generator of R'
所以这一切都很好,因为我们不需要RNG('state'部分)以外的参数来返回R('结果'部分)。
对于自我修改功能,希望使用状态monad来提出以下更具语法结构的版本:
trait Fn[A,R] {
def apply(a: A): (R,Fn[A,R])
}
理想情况下,这可以通过map
和flatMap
方法完成(然后可以通过Scala自动对其进行加糖处理)。
然而,与Rand示例不同,Fn采用类型为A的参数。
使用状态monad,这种事情仍然可以代表吗? 如果没有,它仍然可以表示为monand,如果是这样,那么如何将map或flatMap中的任何一个视为基本*?
*我提到了最后一点,因为FPiS monad特性似乎将map视为基本操作。
答案 0 :(得分:3)
这应该没事;显而易见的方法将起作用:
def applyState[A, R](a: A) = State(fn: Fn[A, R] => fn.apply(a))
val composedState = for {
firstResult <- applyState[Int, Thingy](2)
secondResult <- applyState[Int, Thingy](4)
} yield secondResult
composedState.run(new Fn[Int, Thingy]{...})