ocaml多态变体类型推断类型太一般

ocaml多态变体类型推断类型太一般,ocaml,polymorphic-variants,Ocaml,Polymorphic Variants,我有这个密码 let my_fun: [`X | `Y | `Z] -> [`Z | `Y] = function | `X -> `Y | x -> x 它不会使用消息进行编译 11 | | x -> x ^ Error: This expression has type [ `X | `Y | `Z ] but an expression was expected of type [ `Y | `Z ] T

我有这个密码

let my_fun: [`X | `Y | `Z] -> [`Z | `Y] = function
  | `X -> `Y
  | x -> x
它不会使用消息进行编译

11 |   | x -> x
          ^
Error: This expression has type [ `X | `Y | `Z ]
       but an expression was expected of type [ `Y | `Z ]
       The second variant type does not allow tag(s) `X

如果函数永远不能返回'X',为什么complire不能推断出类型
[
Z
Y]

如果
X
的类型被推断为
[`Y |`Z]
,那么它就不能用于类型
[`X |`Y |`Z]
这会很奇怪,因为它绑定到该类型的参数

您可以使用
作为
模式来获得具有优化类型的绑定,如下所示:

let my_fun: [`X | `Y | `Z] -> [`Y | `Z] = function
  | `X -> `Y
  | (`Y | `Z) as yz -> yz
如果您想对许多情况下的多态变体执行此操作,
#type_name
模式非常有用

为什么编译器不能推断[Z | Y]类型,如果很明显,`X永远不能从函数返回

一个简单的例子是:

if false then 0 else "hello"
编译器必须拒绝它,因为在ML语言中键入要求两个分支具有相同的类型1,并且类型
int
string
不能统一;这是正确的,即使您可以说表达式的计算结果不可能为0(请记住,从形式上讲,我们计算的表达式不属于定义的语言的一部分是没有意义的)

match
表达式中,所有子句的左侧部分的类型必须统一到要匹配的表达式的类型。因此,最后一个子句中的
x
函数中的隐式参数具有相同的类型,即签名中声明的输入类型。无论
`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
另见


[1]为了进行比较,在动态键入的Common Lisp中,等效表达式是有效的;SBCL编译器进行的静态分析可以推断其类型,即长度为5的字符串:

> (describe (lambda () (if nil 0 "hello")))
....
Derived type: (FUNCTION NIL
               (VALUES (SIMPLE-ARRAY CHARACTER (5)) &OPTIONAL))

好的,所以没有办法,如何在不列举所有情况的情况下减去一个类型变量?依我的直觉,编译器可以知道,在第二种情况下,
x
变量不能再是`x,因为它是在第一种情况下单独出现的