簡體   English   中英

使用Monad在Scala中進行狀態計算

[英]Stateful computations in Scala using monads

我一直在嘗試學習Scala中的函數式編程,最終設法了解如何使用for理解與狀態一起工作:

#!/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)

盡管這種方法運行良好,但我無法使用狀態monad進行類似操作,但它比Option更為復雜,因為它需要額外的類型。 我如何使用狀態monad來執行與此代碼類似的操作?

編輯:顯然,我的問題尚不清楚。 我想使用monad特性來運行它,就像我從“ 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 = stateMonad [Int]的實例來執行計算。

經過嘗試后,我設法使其正常運行。 所以,我想我最終會回答我自己的問題。 解決方案是

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了,但是我認為這樣做更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM