fun-girlz


Monada stanu

Poświęcimy teraz chwilę na zaimplementowanie trochę bardziej logistycznie skomplikowanej monady, czyli monady stanu. Używamy jej aby propagować stan przez obliczenia.

1: 
type State<'TState, 'TResult> = State of ('TState -> 'TResult * 'TState)

Nasze obliczenie otrzyma pewien stan, a następnie zwróci rezultat obliczeń i nowy stan. Ale to wszystko będzie ukryte od programisty, który będzie tylko posługiwał się pewnymi prymitywami.

Zadanie

Napisz funkcje:

  • stateReturn : 'a -> State<'t, 'a>, która nie zmieniając stanu zwraca podaną wartość
  • stateRun : State<'t, 'a> -> 't -> 'a * 't, która przyjmuje monadę stanu i pewien stan początkowy i zwraca parę (wynik, nowy stan)
  • stateBind : State<'t, 'a> -> ('a -> State<'t, 'b>) -> State<'t, 'b>
  • stateGet : unit -> State<'t, 't> to jest w zasadzie wartość monadyczna, która w wyniu ma aktualny stan
  • statePut : 't -> State<'t, unit>, która ustawia stan na podany
  • stateModify : ('t -> 't) -> State<'t, unit>, która modyfikuje stan podaną funkcją

A na koniec utwórz środowisko state { }, które pozwoli uruchomić poniższy kawałek kodu:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
//napisany przez was wcześniej Random
type RandomState<'a> = State<Random, 'a>

let nextRandomM = 
    state {
        let! r = stateGet()
        let (x, r') = nextRandom r
        do! statePut r'
        return x
    }

let rec randomArrayM n = 
    state {
        if n <= 0 then return []
        else
            let! t = randomArrayM (n-1)
            let! r = nextRandomM
            return (r::t)
    }

let runRandom seed =
    let (x, _) = stateRun (randomArrayM 10) seed
    in x

Pytania? Jeśli wszystko jasne, to przechodzimy do następnego modułu

Multiple items
union case State.State: ('TState -> 'TResult * 'TState) -> State<'TState,'TResult>

--------------------
type State<'TState,'TResult> = | State of ('TState -> 'TResult * 'TState)

Full name: State_monad.State<_,_>
Multiple items
union case Random.Random: int -> Random

--------------------
type Random = | Random of int

Full name: State_monad.Random
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
val nextRandom : Random -> int * Random

Full name: State_monad.nextRandom
val s : int
val s' : int
namespace System
type Int32 =
  struct
    member CompareTo : value:obj -> int + 1 overload
    member Equals : obj:obj -> bool + 1 overload
    member GetHashCode : unit -> int
    member GetTypeCode : unit -> TypeCode
    member ToString : unit -> string + 3 overloads
    static val MaxValue : int
    static val MinValue : int
    static member Parse : s:string -> int + 3 overloads
    static member TryParse : s:string * result:int -> bool + 1 overload
  end

Full name: System.Int32
field int.MaxValue = 2147483647
val stateReturn : x:'a -> State<'b,'a>

Full name: State_monad.stateReturn
val x : 'a
val s : 'b
val stateRun : State<'a,'b> -> s:'a -> 'b * 'a

Full name: State_monad.stateRun
val f : ('a -> 'b * 'a)
val s : 'a
val stateBind : m:State<'a,'b> -> f:('b -> State<'a,'c>) -> State<'a,'c>

Full name: State_monad.stateBind
val m : State<'a,'b>
val f : ('b -> State<'a,'c>)
val x : 'b
val s' : 'a
val stateGet : unit -> State<'t,'t>

Full name: State_monad.stateGet
val s : 't
val statePut : s:'t -> State<'t,unit>

Full name: State_monad.statePut
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val stateModify : f:('t -> 't) -> State<'t,unit>

Full name: State_monad.stateModify
val f : ('t -> 't)
Multiple items
type StateBuilder =
  new : unit -> StateBuilder
  member Bind : m:State<'a,'b> * f:('b -> State<'a,'c>) -> State<'a,'c>
  member Return : x:'d -> State<'e,'d>

Full name: State_monad.StateBuilder

--------------------
new : unit -> StateBuilder
val this : StateBuilder
member StateBuilder.Return : x:'d -> State<'e,'d>

Full name: State_monad.StateBuilder.Return
val x : 'd
member StateBuilder.Bind : m:State<'a,'b> * f:('b -> State<'a,'c>) -> State<'a,'c>

Full name: State_monad.StateBuilder.Bind
val state : StateBuilder

Full name: State_monad.state
type RandomState<'a> = State<Random,'a>

Full name: State_monad.RandomState<_>
val nextRandomM : State<Random,int>

Full name: State_monad.nextRandomM
val r : Random
val x : int
val r' : Random
val randomArrayM : n:int -> State<Random,int list>

Full name: State_monad.randomArrayM
val n : int
val t : int list
val r : int
val runRandom : seed:Random -> int list

Full name: State_monad.runRandom
val seed : Random
val x : int list
F# Project