10

计算表达式中的方法的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()

下面的代码是允许的

identity {
    printf "Hello World"
    return 1
}

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

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

identity {
    if true then printf "Hello World"
    return 1
}

为什么编译器坚持调用Zero分支else?这背后的直觉是什么?

4

1 回答 1

6

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

我会处理这些案例。

if和都是else语法计算表达式

identity {
    if true then return 1 else return 2
    return 1
}

翻译为:

identity.Combine(
    if true then identity.Return(1) else identity.Return(2), 
    identity.Return(1)
)

缺少一个分支

identity {
    if true then return 1
    return 1
}

翻译为:

identity.Combine(
    if true then identity.Return(1) else identity.Zero(), 
    identity.Return(1)
)

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

identity {
    if true then printf "Hello World" else ()
    return 1
}

翻译为:

identity.Combine(
    if true then printf "Hello World" else (); identity.Zero(), 
    identity.Return(1)
)

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

编辑:我最近做了更多的研究,发现我原来的答案是不正确的。

于 2014-12-17T19:03:56.467 回答