计算表达式中Zero
方法的msdn documentation表示
在计算表达式中调用
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
分支调用{{1}}?这背后的直觉是什么?
答案 0 :(得分:6)
是否需要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
的转换仍然会发生。当if
部分在语法上不是计算表达式时,最后一种情况也适用于没有else
的{{1}}。