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,因为它是在第一种情况下单独出现的