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

时间:2014-12-17 17:36:30

标签: f# monads computation-expression

计算表达式中Zero方法的msdn documentation表示

  

在计算表达式中调用elseif...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分支调用{{1}}?这背后的直觉是什么?

1 个答案:

答案 0 :(得分:6)

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

我会查看案件。

ifelse都是语法计算表达式

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语句返回有效的monadic值,转换也会发生,而使用Zero的转换仍然会发生。当if部分在语法上不是计算表达式时,最后一种情况也适用于没有else的{​​{1}}。

编辑:我最近做了一些研究,发现原来的答案是错误的。