如果很明显 `X 永远不能从函数中返回,为什么编译器不能推断类型 [Z |Y]?
一个更简单的例子是:
if false then 0 else "hello"
编译器必须拒绝它,因为在 ML 语言中键入要求两个分支具有相同的类型1,并且类型和不能统一;这是真的,即使您可以说表达式不可能计算为 0(但请记住,从形式上讲,说我们计算一个不属于定义的语言的表达式是没有意义的)。 int
string
在一个match
表达式中,所有子句的左边部分的类型必须统一到被匹配的表达式的类型。所以x
在最后一个子句中的类型与 in 中的隐式参数相同function
,即签名中声明的输入类型。无论在该上下文中是否`X
是有效值,这都是正确的。
您需要枚举所有有效的案例;如果您在代码中经常需要它,那么您最好为此编写一个专用函数:
let f : ([> `Y | `Z ] -> [`Y | `Z ] option) = function
| (`Y|`Z) as u -> (Some u)
| _ -> None;
例如:
# f `O;;
- : [ `Y | `Z ] option = None
# f `Y;;
- : [ `Y | `Z ] option = Some `Y
另请参阅多态变体的集合论类型(pdf)
[1]作为对比,在动态类型的Common Lisp中,等价表达式是有效的;SBCL 的编译器所做的静态分析可以推断其类型,即长度为 5 的字符串:
> (describe (lambda () (if nil 0 "hello")))
....
Derived type: (FUNCTION NIL
(VALUES (SIMPLE-ARRAY CHARACTER (5)) &OPTIONAL))