让力学!在计算表达式中

Art*_*his 3 f# computation-expression

我目前正在研究神话般的fsharpforfunandprofit网站的计算表达系列,我对计算系列的第4课"包装类型"有疑问.我已经尝试了进一步阅读,但有一个重要的概念,我没有抓住.

实际上,我确实理解bind的定义:

member Bind : M<'T> * ('T -> M<'U>) -> M<'U>
Run Code Online (Sandbox Code Playgroud)

但有一件事我不明白是在使用它时在计算表达式中使用它的魔力!:

例如:

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''
Run Code Online (Sandbox Code Playgroud)

getCustomerId"Alice"给我回M <'T>,但是custId 已经是打开过的'T,我无法看到这个魔术怎么工作......

它是隐藏在let中的代码的一部分!Fsharp核心组件内的指令?有人可以向我解释这是怎么回事!从包装中取出T'?

谢谢你的解释

Car*_*ten 6

这个:

let product'' = 
    dbresult {
        let! custId = getCustomerId "Alice"
        let! orderId = getLastOrderForCustomer "" // error!
        let! productId = getLastProductForOrder orderId 
        printfn "Product is %s" productId
        return productId
        }
Run Code Online (Sandbox Code Playgroud)

desugar to like like(将monad类型命名为just 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)))))))
Run Code Online (Sandbox Code Playgroud)

所以基本上你得到Bind每个级别let!(你通常可以忽略Delay)

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