type Async<'a> = Async of (('a -> unit) * (exn -> unit) -> unit)
let app (Async x) = x
let unit a = Async (fun (cont, _) -> cont a)
let bind m k = Async (fun (cont, econt) -> let c = fun a -> try app (k a) (cont, econt) with exn -> econt exn app m (c, econt))
let catch p = Async (fun (cont, _) -> app p (cont << Choice2_1, cont << Choice2_2))
let start p = app p ((fun () -> ()), (fun exn -> raise exn))
type Async<'a> with static member Run p = let res = ref None // val res : Choice<'a, exn> option ref let cont = fun r -> res := Some r; unit () start (bind (catch p) cont) match Option.get !res with | Choice2_1 a -> a | Choice2_2 exn -> raise exn