Skip to content

Instantly share code, notes, and snippets.

@palladin
Created September 17, 2012 13:18
Show Gist options
  • Select an option

  • Save palladin/3737214 to your computer and use it in GitHub Desktop.

Select an option

Save palladin/3737214 to your computer and use it in GitHub Desktop.
Monadic Trampoline
type TrampValue<'T> =
| DelayValue of Delay<'T>
| ReturnValue of Return<'T>
| BindValue of IBind<'T>
and ITramp<'T> =
abstract member Value : TrampValue<'T>
abstract member Run : unit -> 'T
and Delay<'T>(f : unit -> ITramp<'T>) =
member self.Func = f
interface ITramp<'T> with
member self.Value = DelayValue self
member self.Run () = (f ()).Run()
and Return<'T>(x :'T) =
member self.Value = x
interface ITramp<'T> with
member self.Value = ReturnValue self
member self.Run () = x
and IBind<'T> =
abstract Bind<'R> : ('T -> ITramp<'R>) -> ITramp<'R>
and Bind<'T, 'R>(tramp : ITramp<'T>, f : ('T -> ITramp<'R>)) =
interface IBind<'R> with
member self.Bind<'K>(f' : 'R -> ITramp<'K>) : ITramp<'K> =
new Bind<'T, 'K>(tramp, fun t -> new Bind<'R, 'K>(f t, (fun r -> f' r)) :> _) :> _
interface ITramp<'R> with
member self.Value = BindValue self
member self.Run () =
match tramp.Value with
| BindValue b -> b.Bind(f).Run()
| ReturnValue r -> (f r.Value).Run()
| DelayValue d -> (new Bind<'T, 'R>(d.Func (), f) :> ITramp<'R>).Run()
// Builder
type TrampBuilder() =
member self.Return a = new Return<_>(a) :> ITramp<_>
member self.Bind(tramp, f) =
new Bind<'T, 'R>(tramp, f) :> ITramp<'R>
member self.Delay f =
new Delay<_>(f) :> ITramp<_>
let tramp = new TrampBuilder()
let run (tramp : ITramp<'T>) = tramp.Run()
// Example
let rec inc a =
tramp {
if a = 1 then return 1
else
let! x = inc (a - 1)
return x + 1
}
inc 1000000 |> run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment