3

我有以下计算表达式生成器:

type ExprBuilder() = 
    member this.Return(x) =
        Some x

let expr = new ExprBuilder()

我了解方法ReturnZeroCombine的目的,但我不明白下面显示的表达式之间有什么区别:

let a = expr{
    printfn "Hello"
    return 1
} // result is Some 1

let c = expr{
   return 1
   printfn "Hello"
} // do not compile. Combine method required

我也不明白为什么在第一种情况下, printfn语句不需要零方法?

4

1 回答 1

5

在第一个表达式中,您执行了一些计算,结果是 value 1,就是这样。你不需要 a Zero,因为Zero只需要return-less 表达式(这就是为什么它被称为“零” - 它是什么都没有的时候),并且你的表达式确实有一个return.

要专门回答您的问题, “对于 printfn 语句Zero”不是必需的,因为并非表达式中的每一行都会被转换。编译计算表达式时,编译器会在“特殊”点(例如、、等)将它们分解,从而使这些点之间的所有其余代码保持不变。在这种情况下,您的调用只是成为在.let!do!returnprintfnreturn

在第二个表达式中,您执行两个计算:第一个结果是 value 1,第二个结果是Zero(当表达式缺少 a 时,这是隐含的假设return)。但是整个计算表达式不能有两个返回值,它必须有一个。因此,为了将两个计算的结果结合在一起(有人可能会说,将它们结合起来),您需要该Combine方法。

除了Combineand Zero,您还需要实现Delay它才能工作。多部分(即“组合”)计算也包含Delay在内,以允许构建器推迟评估并可能在Combine实现中删除一些部分。

我建议通读Scott Wlaschin 的这篇介绍,特别是关于DelayandRun的第 3 部分。

于 2016-03-26T21:28:21.713 回答