我一直在努力学习Scala中的函数式编程,最后我终于理解了如何使用for comprehension来处理state:
#!/usr/bin/env scala
case class State[A,S](run: S => (A,S)) {
def map[B](f: A => B): State[B,S] =
State(s => {
val (a, s1) = run(s)
(f(a), s1)
})
def flatMap[B](f: A => State[B,S]): State[B,S] =
State(s => {
val (a,s1) = run(s)
f(a).run(s1)
})
}
val increment = State[Unit,Int] {
x => ((),x+1)
}
val read = State[Int,Int] {
x => (x,x)
}
def prog = for {
_ <- increment
x <- read
_ <- increment
y <- read
} yield (x,y)
val ans = prog.run(0)._1
println(ans)虽然这运行得很好,但我没有设法使用state monad做类似的事情,它比Option更复杂,因为它需要一个额外的类型。如何使用状态monad执行类似于此代码的操作?
编辑:显然,我的问题不清楚。我想使用一个monad特征来运行它,就像我从"Functional programming in Scala“中获得的那样:
def stateMonad[S] = new Monad[({type lambda[x] = State[S,x]})#lambda] {
def unit[A](a: => A): State[S,A] = State(s => (a, s))
def flatMap[A,B](st: State[S,A])(f: A => State[S,B]): State[S,B] =
st flatMap f
}然后通过像val M= stateMonadInt这样的东西实例化它来执行计算。
发布于 2017-05-19 04:25:47
在尝试之后,我设法让它正常工作。所以,我想我会回答我自己的问题。解决方案是
trait Monad[M[_]] {
def unit[A](a: => A): M[A]
def flatMap[A,B](ma: M[A])(f: A => M[B]): M[B]
}
class StateMonad[S] extends Monad[({type lambda[x] = State[x,S]})#lambda] {
def unit[A](a: => A): State[A,S] = State(s => (a, s))
def flatMap[A,B](st: State[A,S])(f: A => State[B,S]): State[B,S] =
st flatMap f
def increment: State[Unit,Int] = State(x => ((),x+1))
def read: State[Int,Int] = State(x => (x,x))
}
val m = new StateMonad[Int]
def prog = for {
_ <- m.increment
x <- m.read
_ <- m.increment
y <- m.read
} yield (x,y)其思想是使StateMonad类继承自Monad,并将处理状态的所有函数作为StateMonad类的方法包含在内。正如前面所指出的,我之前的代码可能已经被认为是monad,但我认为这样做更好。
https://stackoverflow.com/questions/44055973
复制相似问题