Created
August 31, 2021 20:24
-
-
Save njlr/52c52906551579e67e30b8f158905509 to your computer and use it in GitHub Desktop.
State monad in F#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[<Struct>] | |
type Stateful<'state, 'result> = | |
Stateful of ('state -> 'state * 'result) | |
type Delayed<'state, 'result> = unit -> Stateful<'state, 'result> | |
module State = | |
let update f = | |
Stateful (fun state -> f state, ()) | |
let just x = | |
Stateful (fun state -> state, x) | |
let bind (m : Stateful<'state, 't>) (f : 't -> Stateful<'state, 'u>) : Stateful<'state, 'u> = | |
Stateful (fun s1 -> | |
let (Stateful m) = m | |
let s2, x = m s1 | |
let (Stateful f) = f x | |
f s2) | |
let doWhile (guard : unit -> bool) (body : Delayed<'state, unit>) = | |
let rec loop m = | |
if guard () | |
then | |
bind m (fun () -> loop (body ())) | |
else | |
m | |
loop (just ()) | |
let run state (m : Stateful<'state, 't>) = | |
let (Stateful m) = m | |
m state | |
[<AutoOpen>] | |
module ComputationExpression = | |
open State | |
type StatefulBuilder() = | |
member this.Bind(m, f) = | |
bind m f | |
member this.Return(x) = | |
just x | |
member this.Zero() = | |
just () | |
member this.Delay(f : Delayed<'state, 'result>) = | |
f | |
member this.Run(f : Delayed<'state, 'result>) = | |
f () | |
member this.While(guard, body) = | |
doWhile guard body | |
let state = StatefulBuilder() | |
state { | |
return 3 | |
} | |
|> State.run () | |
|> printfn "%A" | |
state { | |
do! State.update (fun x -> x + 1) | |
do! State.update (fun x -> x * 2) | |
} | |
|> State.run 3 | |
|> printfn "%A" | |
state { | |
let mutable i = 0 | |
while i < 3 do | |
do! State.update (fun state -> i :: state) | |
i <- i + 1 | |
} | |
|> State.run [] | |
|> printfn "%A" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment