我有以下计算表达式构建器:
type ExprBuilder() =
member this.Return(x) =
Some x
let expr = new ExprBuilder()
我理解方法返回,零和组合的目的,但我不明白下面显示的表达式有什么区别:
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 语句中不需要第一种情况 Zero 方法?
答案 0 :(得分:5)
在第一个表达式中,执行一些导致值1
的计算,以及它的结果。你不需要Zero
,因为Zero
只需要return
- 更少的表达(这就是为什么它被称为&#34} ;零" - 当没有任何东西时它是什么东西),你的表达式确实有return
。
要专门回答您的问题,不需要Zero
" 用于printfn语句",因为并非表达式中的每一行都会被转换。在编译计算表达式时,编译器会在" special"点,例如let!
,do!
,return
等,将所有其余代码保留在这些点之间。在这种情况下,您的printfn
调用只会成为在return
之前执行的代码的一部分。
在第二个表达式中,您执行两个计算:第一个计算结果为1
,第二个计算结果为Zero
(当表达式缺少时隐式假设一个return
)。但是整个计算表达式不能有两个返回值,它必须有一个。因此,为了将两个计算的结果结合在一起(可能会说,结合它们),您需要Combine
方法。
除Combine
和Zero
外,您还需要实施Delay
才能实现此目的。 Multipart(即"组合")计算也包含在Delay
中,以便允许构建器推迟评估并可能删除Combine
实现中的某些部分。
我建议您阅读Scott Wlaschin撰写的this introduction,特别是part 3 about Delay
and Run
。