计算表达式中Zero
方法的 msdn 文档指出
为计算表达式中
if...then
表达式的空else
分支调用。
假设我们使用的是未定义Zero
的identity
计算生成器。
let IdentityBuilder() =
member this.Bind(i, f) = f i
member this.Return(i) = i
let identity = new IdentityBuilder()
允许使用以下代码
identity {
printf "Hello World"
return 1
}
但是,不允许使用以下代码,并且由于编译器错误而失败
仅当计算表达式生成器定义"Zero"方法时,才能使用此控件构造
identity {
if true then printf "Hello World"
return 1
}
为什么编译器坚持为else
分支调用Zero
?这背后的直觉是什么?
Zero
的实现取决于如何将if
语句转换为来自monadic语法的函数调用。如果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
语句返回有效的 monadic 值,使用 Zero
的翻译仍然会发生转换。最后一种情况也适用于没有else
的if
,当then
部分在语法上不是计算表达式时。
编辑:我最近做了更多的研究,发现我原来的答案是不正确的。