Skip to content

Instantly share code, notes, and snippets.

@0017031
Forked from thomasd16/running.fs
Created February 27, 2024 07:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0017031/5b1dbc6a2cc87c25d7ab6e64c4aace61 to your computer and use it in GitHub Desktop.
Save 0017031/5b1dbc6a2cc87c25d7ab6e64c4aace61 to your computer and use it in GitHub Desktop.
Full Trampoline monad
//This just weves the prepareStackFree function in through the running function
//what we end up with is what looks like a nested monad
type 't Running =
|Result of 't
|Step of (unit->'t Running)
type 't RunningBuilder = RunningBuilder of ((('t->'t RunningBuilder) list)->'t Running)
type RunningMonad() =
member this.Bind(RunningBuilder expr,fn) =
RunningBuilder(fun stack-> Step(fun()->expr(fn::stack)))
member this.Delay(fn) =
RunningBuilder(fun stack->Step(fun()->
let (RunningBuilder r) = fn ()
r stack))
member this.ReturnFrom(x) = x
member this.Return(value) =
RunningBuilder(function
|[]->Result(value)
|x::xs->Step(fun ()->
let (RunningBuilder r) = (x value)
r xs))
let running = RunningMonad()
let rec add1 n = running {
if n = 0 then return 0
else
let! next = add1 (n-1)
return next+1
}
let rec run = function
|Result(x)->x
|Step(fn)-> run (fn())
[<EntryPoint>]
let main argv =
let (RunningBuilder(r)) = add1 100000
printfn "%i" (run (r []))
0 // return an integer exit code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment