type State<'s, 'a> = State of ('s ->'a * 's)
(*
//Runを使わないバージョン
let (>>=) (State g) f =
State <| fun s ->
let v,s' = g s
match f v with
| State h -> h s'
*)
let Run state (State s) = s state
let (>>=) m f =
State <| fun s ->
let v,s' = Run s m
Run s' <| f v
type StateBuilder () =
member this.Bind(m, f) = m >>= f
member this.Return x = State <| fun s -> x, s
let state = StateBuilder ()
//stateモナドを操作する関数群
let Get = State <| fun s -> (s, s)
let Getf = fun _ -> State <| fun s -> (s,s)
let Put s = State <| fun _ -> ((), s)
let Modify f = state {
let! s = Get
do! Put (f s)
}
let Test1 = state{
let! a = Get // a=10 (10,10)
do! Put (a+5) // ((),15)
do! Modify ((+)5) // ((),20)
let! b = Get // b=20 (20,20)
let! d = Modify ((+)10) // d=() ((),30)
return b // (20,30)
}
Test1 |> Run 10 |> printfn "%A"
let Test2 = state{
let! a = Getf () //a=[1;2] ([1;2],[1;2])
let! b = Put (3::a) //b=() ([(),[3;1;2])
let! c = Getf () //c=[3;1;2] ([3;1;2],[3;1;2])
return (List.sum c) //(6,[3;1;2])
}
Test2 |> Run [1;2] |> printfn "%A"