2017-05-18 1 views
1

Ich habe versucht, die funktionale Programmierung in Scala zu lernen, und ich es endlich geschafft, zu verstehen, wie das mit Staat zu arbeiten für das Verständnis verwenden:Stateful Berechnungen in Scala mit Monaden

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

Obwohl diese fein läuft, Ich habe es nicht geschafft, etwas Ähnliches mit einer Zustands-Monade zu machen, es ist komplizierter als zB Option, weil es einen extra Typ braucht. Wie mache ich etwas Ähnliches wie dieser Code mit einer State Monade?

EDIT: Anscheinend war meine Frage nicht klar. Ich möchte dies mit einer Monade Eigenschaft laufen, wie diese, die ich von „Funktionale Programmierung in Scala“ nahm:

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 
} 

Und dann die Berechnung durchführen, indem diese mit so etwas wie val M = stateMonad [Int] Instanziieren .

+1

Konnte Frage nicht verstehen. Ihr Code ist die Umsetzung der staatlichen Monade. – Zernike

+0

Ich habe die Frage bearbeitet, um es zu klären. –

Antwort

2

Nachdem ich es versucht hatte, gelang es mir, es zum Laufen zu bringen. Also denke ich, dass ich am Ende meine eigene Frage beantworten werde. Die Lösung ist

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) 

Die Idee ist es, die StateMonad Klasse erbt von Monade zu machen, und umfasst alle Funktionen, den Staat als Methoden der StateMonad Klasse zu manipulieren. Wie bereits erwähnt, könnte mein vorheriger Code bereits als Monade betrachtet werden, aber ich denke, es ist besser, wenn man so vorgeht.