Implementing the Haskell-MaybeMonad in F# - how can we get this lazy?

前端 未结 2 1551
盖世英雄少女心
盖世英雄少女心 2021-02-10 04:22

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

相关标签:
2条回答
  • 2021-02-10 04:43

    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
    }
    
    0 讨论(0)
  • 2021-02-10 05:06

    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
    
    0 讨论(0)
提交回复
热议问题