chúng tôi đang cố gắng tạo mẫu Haskell-MaybeMonad từ http://www.haskell.org/all_about_monads/html/maybemonad.html trong F #.Thực hiện Haskell-MaybeMonad trong F # - làm thế nào chúng ta có thể có được điều này lười biếng?
Ý tưởng là tìm kiếm địa chỉ thư trong hai từ điển. Nếu một trong hai tra cứu trả về kết quả, chúng tôi sẽ xem xét kết quả thứ ba.
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()
let maybe = MaybeBuilder()
//Sample dictionaries
let fullNamesDb =
[("Bill Gates", "[email protected]")
("Bill Clinton", "[email protected]")
("Michael Jackson", "[email protected]")
("No Pref Guy", "[email protected]")]
|> Map.ofList
let nickNamesDb =
[("billy", "[email protected]")
("slick willy", "[email protected]")
("jacko", "[email protected]") ]
|> Map.ofList
let prefsDb =
[("[email protected]", "HTML")
("[email protected]", "Plain")
("[email protected]", "HTML")]
|> Map.ofList
let mplus m1 m2 = if m1 <> None then m1 else m2
let (+) = mplus
let lookUp name = maybe {
let! combined = fullNamesDb.TryFind name + nickNamesDb.TryFind name
return! prefsDb.TryFind combined
}
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
System.Console.ReadKey() |> ignore
Vấn đề là chúng tôi thực hiện lần tra cứu thứ hai ngay cả khi lần đầu tiên trả về kết quả. Điều tốt đẹp về Haskell là ở đây, rằng nó đánh giá lười biếng. Bây giờ chúng tôi tìm kiếm một cái gì đó tương tự trong F #. Chúng tôi đã thử những điều sau nhưng có vẻ xấu xí và dường như phá vỡ ý tưởng đóng gói logic có thể trong trình tạo:
let mplus m1 m2 = if m1 <> None then m1 else m2()
let (+) = mplus
let lookUp name = maybe {
let! combined = fullNamesDb.TryFind name + fun _ -> nickNamesDb.TryFind name
return! prefsDb.TryFind combined
}
Có giải pháp nào tốt hơn không?
Kính trọng, forki
Ý tưởng tuyệt vời. Điều đó thật tuyệt vời. – forki23