让的机制!在计算表达式中

the mechanics of let! in computation expressions

我目前正在研究神话般的 fsharpforfunandprofit 网站的计算表达式系列,我对计算系列的第 4 课 "wrapped type" 有疑问。我尝试进一步阅读,但有一个重要概念我没有掌握。

其实我理解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 已经是 unwrapped '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)))))))

所以基本上每个 let! 你都会得到一个 Bind 等级(你通常可以忽略 Delay

如您所见,计算表达式 语法比嵌套 Binds 语法好得多 - 大多数支持某种单子表达式的语言都具有类似的 语法糖 - 甚至 C#(from ... in ... select 又名 LINQ)