Skip to content

Instantly share code, notes, and snippets.

@thomasd16
Created July 17, 2017 22:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save thomasd16/017e550f4fd5c5ffd110cb7e2f337b88 to your computer and use it in GitHub Desktop.
Save thomasd16/017e550f4fd5c5ffd110cb7e2f337b88 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