we are trying to build the Haskell-MaybeMonad sample from http://www.haskell.org/all_about_monads/html/maybemonad.html in F#.
The idea is to search for a mailaddress in
There's always Lazy, which is effectively what you have here but with different syntax:
let mplus m1 (m2 : Lazy<'a option>) =
match m1 with
| Some _ as m -> m
| None -> m2.Force()
let (+) = mplus
let lookUp name = maybe {
let! combined = fullNamesDb.TryFind name + lazy (nickNamesDb.TryFind name)
return! prefsDb.TryFind combined
}
You can implement additional methods Run/Combine in MaybeBuilder so result shall be the following:
let bindM x k =
match x with
| Some value -> k value
| None -> None
let returnM x = Some x
type MaybeBuilder() =
member this.Bind(x, k) = bindM x k
member this.Return(x) = returnM x
member this.ReturnFrom(x) = x
member this.Delay(f) = f
member this.Combine(a, b) = if Option.isSome a then a else b()
member this.Run(f) = f()
let maybe = MaybeBuilder()
//Sample dictionaries (the same with original sample)
let fullNamesDb = ...
let nickNamesDb = ...
let prefsDb = ....
let lookUp name =
let findName m = maybe {
let! v = Map.tryFind name m
return! prefsDb.TryFind v
}
maybe {
return! findName fullNamesDb
return! findName nickNamesDb
}
let billGatesPref = lookUp "Bill Gates" |> printfn "%A" // Some "HTML"
let billyPref = lookUp "billy" |> printfn "%A" // Some "HTML"
let billClintonPref = lookUp "Bill Clinton" |> printfn "%A" // Some "Plain"
let steffenPref = lookUp "Steffen" |> printfn "%A" // None
let noPref = lookUp "No Pref Guy" |> printfn "%A" // None