为什么在OCaml类型检查中有两个不同的错误消息?

时间:2015-01-28 12:02:39

标签: 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) 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

最后一条错误讯息有我不明白的地方。在分析具有三个令牌但没有括号的最后一个表达式时,('c -> 'd) * 'e的ocaml替换类型'c * 'd是什么?

Function application我只能猜测(但不能说)这可能与关联有关,以及ocaml如何看待函数和参数并列。关于在哪里看的任何提示?

1 个答案:

答案 0 :(得分:3)

简而言之,您只是触及统一算法的不同路径,这是OCaml类型推断的核心。

两种情况,括号和最后一种在语义上是等价的,但由于语法中的某些微妙性,表示略有不同。 (这是因为语法和括号中有规则和括号创建了一个,但实际上这并不重要。)

由于我们的语法树略有不同,统一在这里选择了两条不同的路径。在第一种情况下,它首先尝试使用带括号的简单表达式进行类型检查。在第二种情况下,它试图推断整体函数类型,然后转移到参数的统一(粗略)。在任何情况下,类型检查员都会尽快停止。这就是为什么在第一个案例中,typechecker甚至没有试图照看括号,因为他已经知道,表达式无效。

第二种情况的推理可以表示如下:为了使这个表达式x y z能够进行类型检查,x y应该计算出能够接受z表达式的函数表达式,即,(x y) : 'c -> 'd,其中'c'd只是类型变量。由于x的类型为'a * 'b -> 'a,这意味着'a必须包含'c -> 'd类型,替换'a我们会得到y类型的推断为('c -> 'd) * 'e。现在,我们查看y的实际类型,并看到它具有完全不同的类型,无法与推断的类型统一。我们提出错误。