在计算表达式中为if..then构造的else分支调用Zero后面的直觉

Tej*_*rma 10 monads f# computation-expression

计算表达式中方法的msdn文档说明了这Zero一点

在计算表达式中调用表达式的空else分支if...then.

假设我们正在使用一个identity没有Zero定义的计算构建器.

let IdentityBuilder() = 
    member this.Bind(i, f) = f i
    member this.Return(i) = i

let identity = new IdentityBuilder()
Run Code Online (Sandbox Code Playgroud)

允许使用以下代码

identity {
    printf "Hello World"
    return 1
}
Run Code Online (Sandbox Code Playgroud)

但是,不允许使用以下代码,并且编译器错误会失败

仅当计算表达式构建器定义"零"方法时,才可以使用此控件构造

identity {
    if true then printf "Hello World"
    return 1
}
Run Code Online (Sandbox Code Playgroud)

为什么编译坚持呼吁Zeroelse分支?这背后的直觉是什么?

mrm*_*reg 6

是否Zero需要实现取决于if语句如何从monadic语法转换为函数调用.如果a的两个分支if都是语法计算表达式,则翻译不涉及Zero.在其中一个分支在语法上不是计算表达式或缺少翻译表达式的情况下Zero.

我会仔细检查一下.

双方ifelse在语法上计算表达式

identity {
    if true then return 1 else return 2
    return 1
}
Run Code Online (Sandbox Code Playgroud)

翻译为:

identity.Combine(
    if true then identity.Return(1) else identity.Return(2), 
    identity.Return(1)
)
Run Code Online (Sandbox Code Playgroud)

缺少一个分支

identity {
    if true then return 1
    return 1
}
Run Code Online (Sandbox Code Playgroud)

翻译为:

identity.Combine(
    if true then identity.Return(1) else identity.Zero(), 
    identity.Return(1)
)
Run Code Online (Sandbox Code Playgroud)

指定了两个分支,但它们不是语法计算表达式

identity {
    if true then printf "Hello World" else ()
    return 1
}
Run Code Online (Sandbox Code Playgroud)

翻译为:

identity.Combine(
    if true then printf "Hello World" else (); identity.Zero(), 
    identity.Return(1)
)
Run Code Online (Sandbox Code Playgroud)

最后一种情况有点令人感兴趣,因为即使if语句返回有效的monadic值,翻译Zero仍然会发生.最后一种情况也适用于if没有a 的情况,else当该then部分在语法上不是计算表达式时.

编辑:我最近做了一些研究,发现我的原始答案是不正确的.