<Query Kind="FSharpProgram" />

let m = async { return 3 }
let f t = async { return t + 1 }
let h t = t + 1

let unit t = async { return t }

let unit' t = async.Return t

let result m = Async.RunSynchronously m

printfn "unit: %A, %A" (result (unit 7)) (result (unit' 7))

let bind f m = async.Bind (m, f)

let bind' f m = 
    async {
        let! t = m
        return! f t
    }

let f' m = bind f m
let f'' m = bind' f m

printfn "bind: %A, %A" (result (f' m)) (result (f'' m))

let map h m = async.Bind (m, h >> unit)

let map' h m = 
    async {
        let! t = m
        return h t
    }

let h' m = map h m
let h'' m = map' h m

printfn "map: %A, %A" (result (h' m)) (result (h'' m))

let flat = bind id

let flat' = result

let mm = map f m
let m' = flat mm
let m'' = flat' mm

printfn "flat: %A, %A" (result m') (result m'')

