我怀疑答案必须涉及一些抽象类型理论,但我也非常感谢具体的例子。
答案 0 :(得分:7)
以下答案来自Jeremy Yallop。我从OCaml邮件列表中引用它,因为我找不到发布的在线链接。
[tl; dr:消息的意思是“表达式的类型未知。 为表达式中的变量添加类型注释。“]
背景:私有类型缩写由类型别名定义 用'私人'一词定义。例如,以下内容 定义
type t = private int
为int提供了一种半别名:你可以从类型t转换为 int,但是你不能从int转换为t。执行强制 使用':>'运算符,所以你可以写这样的东西
let f (x : t) = (x :> int)
从私有类型t转换为缩写类型int。
现在,为了检查以下强制是否有效
(x :> int)
编译器需要知道x的类型。可能有几个 候选人:例如,上面的私人类型缩写 范围,如果x具有类型t,则强制有效,但是无操作强制 也是允许的,因此int是另一种合理的可能性。怎么能 编译器在这些替代方案之间进行选择以找到x的类型? 在f的定义中,选择很容易:x是一个函数 带有注释的参数,因此编译器只使用它 注解。这是一个稍微棘手的案例:
let g (y : t) = ()
let h x = (g x, (x :> int))
这里的x是什么类型的?编译器的推理算法检查 从左到右的一对元素,所以这是发生的事情:
但是,如果推理算法检查了a的元素 从右到左对,我们有以下一系列步骤:
最初,当h的类型检查开始时,x的类型是未知的 (2)检查强制(x:> int),编译器猜测 x的类型。在没有其他信息的情况下,它会猜测。 (3)检查并拒绝子表达式g x,因为x具有 输入int,而不是t。
确实,如果我们交换对的元素来模拟这个 第二种行为
let h2 x = ((x :> int), g x)
然后强制被拒绝:
let h x = ((x :> int), g x);;
^
Error: This expression has type int but an expression was expected of type t
因为不依赖于特定订单的程序更好 由推理算法使用,编译器发出警告。您 可以通过注释x:
的绑定来解决警告let h (x : t) = (g x, (x :> int))