为什么在OCaml类型检查中有两条不同的错误消息?
从完整表达式开始,一切都按照ocaml计算器中的预期工作为什么在OCaml类型检查中有两条不同的错误消息?,ocaml,Ocaml,从完整表达式开始,一切都按照ocaml计算器中的预期工作 # fst (fst ((1, 2), 3)) ;; - : int = 1 想象一下传递函数但未能将其置于适当上下文中的结果。我将在这些例子中举例说明: # fst fst ;; # expect error Error: This expression has type 'a * 'b -> 'a but an expression was expected of type 'c * 'd # (fst fst
# fst (fst ((1, 2), 3)) ;;
- : int = 1
想象一下传递函数但未能将其置于适当上下文中的结果。我将在这些例子中举例说明:
# fst fst ;; # expect error
Error: This expression has type 'a * 'b -> 'a
but an expression was expected of type 'c * 'd
# (fst fst) whatever ;;
Error: This expression has type 'a * 'b -> 'a
but an expression was expected of type 'c * 'd
# fst fst whatever ;;
Error: This expression has type 'a * 'b -> 'a
but an expression was expected of type ('c -> 'd) * 'e
最后一条错误消息包含我不理解的内容。在分析最后一个包含三个标记但没有括号的表达式时,是什么使得ocaml将类型('c->'d)*'e
替换为'c*'d
看一下,我只能猜测(但不能说)这可能与关联以及ocaml如何看待并置的函数和参数有关。有没有关于在哪里查找的提示?简言之,您只是找到了统一算法的另一条路径,它位于OCaml类型推断的核心 括号内的两种情况和最后一种情况在语义上是等价的,但由于语法中的一些微妙之处,a的表示略有不同。(这是因为语法中有和规则,括号创建了一个,但实际上这并不重要) 因为我们有稍微不同的语法树,统一在这里选择了两条不同的路径。在第一种情况下,它首先尝试对括号中的简单表达式进行类型检查。在第二种情况下,它试图推断整个函数类型,然后转向参数的统一(大致)。在任何情况下,typechecker都会尽快停止。这就是为什么在第一种情况下,typechecker甚至没有注意括号,因为他已经知道表达式是无效的
第二种情况下的推理可以这样表达:为了让这个表达式
xyz
进行类型检查,xy
应该计算为可以接受z
表达式的函数表达式,即(xy):'c->'d
,其中'c
和'd
只是类型变量。由于x
具有类型'a*'b->'a
,这意味着'a
必须具有类型'c->'d
,替换'a
,我们将y
的类型推断为('c->'d)*'e
。现在,我们看一下y
的实际类型,它有完全不同的类型,不能与推断的类型统一。我们提出了错误 谢谢你的关键词和详细的讨论。FWIW,一个关于链接到一些关于这个问题的文章的问题。这个答案不是100%正确fxy
和(fx)y
在语义上并不相同——这两个语法的可选参数表现不同。这就是为什么它们在语法树中有不同的表示。否则,解析器可能会将它们折叠成一个表示形式。@LeoWhite,好的,我同意。但严格来说,我并不是说,一般来说,fxy
和(fx)y
在语义上是相同的。我只是在谈论OP.@ivg提供的例子。当然,我只是觉得这是对答案的有趣补充。如果不是因为可选参数的复杂性,错误消息可能是相同的。