计算表达式中的零点和组合

sgn*_*gon 3 f# computation-expression

我有以下计算表达式构建器:

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

let expr = new ExprBuilder()
Run Code Online (Sandbox Code Playgroud)

我理解方法Return,ZeroCombine的目的,但我不明白下面的表达式有什么区别:

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

let c = expr{
   return 1
   printfn "Hello"
} // do not compile. Combine method required
Run Code Online (Sandbox Code Playgroud)

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

Fyo*_*kin 5

在第一个表达式中,您执行一些导致值的计算1,就是这样.你不需要一个Zero,因为Zero只需要return无表达式(这就是为什么它被称为"零" - 它就是那里什么都没有),你的表达式确实有一个return.

要专门回答您的问题,Zero" printfn语句 " 不需要,因为表达式中的每一行都不会被转换.当编译计算表达式时,编译器打破了他们在"特殊"的点,如let!,do!,return,等,留下完整的点之间的代码的所有的休息.在这种情况下,您的printfn调用只是在之前执行的代码的一部分return.

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

除了CombineZero,你想也需要实现Delay这个工作.还包括多部分(即"组合")计算Delay,以便允许构建器推迟评估并可能删除Combine实现中的一些部分.

我建议阅读Scott Wlaschin的这篇介绍,特别是关于Delay和的第3部分Run.