我目前正在开发神话般的fsharpforfunandprofit网站的计算表达式系列,并且对计算系列的第4课“包装类型”有疑问。我尝试进一步阅读,但是有一个重要的概念我没有掌握。
实际上,我确实了解bind的定义:
member Bind : M<'T> * ('T -> M<'U>) -> M<'U>
但我目前不了解的一件事是在let!的计算表达式中使用它的魔力:
例如在:
let product'' =
dbresult {
let! custId = getCustomerId "Alice"
let! orderId = getLastOrderForCustomer "" // error!
let! productId = getLastProductForOrder orderId
printfn "Product is %s" productId
return productId
}
printfn "%A" product''
getCustomerId“ Alice”还给我M <'T>,但是custId已经是展开的'T了,我在任何地方都看不到这个魔术的工作原理。
它是隐藏在let中的代码的一部分吗?Fsharp核心程序集中的指令?有人可以向我解释如何出租!把T'从包装中拿出来?
感谢您的解释
这:
let product'' =
dbresult {
let! custId = getCustomerId "Alice"
let! orderId = getLastOrderForCustomer "" // error!
let! productId = getLastProductForOrder orderId
printfn "Product is %s" productId
return productId
}
将脱糖为类似(将monad类型命名为DB<'t>
):
let product'' =
DB.Delay(fun () ->
DB.Bind(getCustomerId "Alice",(fun custId ->
DB.Bind(getLastOrderForCustomer "",(fun orderId ->
DB.Bind(getLastProductForOrder orderId, (fun productId ->
printfn "Product is %s" productId
DB.Return productId)))))))
因此,基本上Bind
每个级别都有一个级别let!
(通常可以忽略Delay
)
如您所见,计算表达式的语法比嵌套的要好得多Binds
-大多数支持某种形式的单子表达式的语言都具有相似的语法糖-甚至是C#(from ... in ... select
又名LINQ)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句