Created
March 24, 2019 04:32
-
-
Save brianberns/818fae16fbde7b7690b7165fead57ab3 to your computer and use it in GitHub Desktop.
Computation monad for mortals: A clearly-explained implementation of the continuation monad
This file contains hidden or 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
/// https://stackoverflow.com/questions/40052256/how-does-continuation-monad-really-work/42062682#42062682 | |
/// A continuation is a function that represents "the rest of the computation". | |
type Cont<'T, 'U> = ('T -> 'U) | |
/// An incomplete computation is a function which, when given a continuation, | |
/// will return a value. | |
type Inc<'T, 'U> = Cont<'T, 'U> -> 'U | |
/// Creates an incomplete computation that holds the given value. | |
let ret (t : 'T) : Inc<'T, _> = | |
fun (cont : Cont<'T, _>) -> cont t | |
/// Composition of incomplete computations. | |
let bind (incT : Inc<'T, _>) (wrap : 'T -> Inc<'U, _>) : Inc<'U, _> = | |
fun (contU : Cont<'U, _>) -> // return an Inc, which is a function that takes a continuation as input | |
incT (fun t -> // force the given incomplete computation to cough up its wrapped value | |
(wrap t) contU) // re-wrap the raw value so it can be sent to the given continuation | |
/// Monad definition. | |
type ContinuationBuilder() = | |
member __.Return(value) = ret value | |
member __.Bind(inc, wrap) = bind inc wrap | |
/// Builder instance. | |
let continuation = ContinuationBuilder() | |
/// Continuation-ized version of Fibonacci function. | |
let rec fib n : Inc<int, _> = | |
continuation { | |
match n with | |
| 0 -> return 0 | |
| 1 -> return 1 | |
| n -> | |
let! x1 = fib (n - 1) | |
let! x2 = fib (n - 2) | |
return x1 + x2 | |
} | |
[<EntryPoint>] | |
let main argv = | |
for i = 0 to 10 do | |
fib i (fun x -> // pass the continuation directly to the fib function | |
printfn "%d: %d" i x) | |
0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment