为什么 OCaml 类型检查中有两条不同的错误消息?
Why two different error messages in OCaml type checking?
从一个完整的表达式开始,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
最后一条错误消息有我不明白的地方。在分析最后一个具有三个标记但没有括号的表达式时,是什么让 ocaml 将类型 ('c -> 'd) * 'e
替换为 'c * 'd
?
看着 Function application 我只能猜测(但不能说)这可能与关联有关,以及 ocaml 如何看待并列的函数和参数。关于在哪里看的任何提示?
简而言之,您只是走上了统一算法的另一条路,那是 OCaml 类型推断的核心。
括号内的这两种情况和最后一种情况在语义上是等价的,但由于语法中的一些细微差别,a 表示略有不同。 (这是因为语法中有 and 规则,括号,创建一个 ,其实这无所谓)。
由于我们的语法树略有不同,统一在这里选择了两条不同的路径。在第一种情况下,它首先尝试对带括号的简单表达式进行类型检查。在第二种情况下,它尝试推断整体函数类型,然后(粗略地)移动到参数的统一。在任何情况下,类型检查器都会尽快停止。这就是为什么在第一种情况下,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
的实际类型,发现它具有完全不同的类型,无法与推断的类型统一。我们提出错误。
从一个完整的表达式开始,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
最后一条错误消息有我不明白的地方。在分析最后一个具有三个标记但没有括号的表达式时,是什么让 ocaml 将类型 ('c -> 'd) * 'e
替换为 'c * 'd
?
看着 Function application 我只能猜测(但不能说)这可能与关联有关,以及 ocaml 如何看待并列的函数和参数。关于在哪里看的任何提示?
简而言之,您只是走上了统一算法的另一条路,那是 OCaml 类型推断的核心。
括号内的这两种情况和最后一种情况在语义上是等价的,但由于语法中的一些细微差别,a 表示略有不同。 (这是因为语法中有 and 规则,括号,创建一个 ,其实这无所谓)。
由于我们的语法树略有不同,统一在这里选择了两条不同的路径。在第一种情况下,它首先尝试对带括号的简单表达式进行类型检查。在第二种情况下,它尝试推断整体函数类型,然后(粗略地)移动到参数的统一。在任何情况下,类型检查器都会尽快停止。这就是为什么在第一种情况下,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
的实际类型,发现它具有完全不同的类型,无法与推断的类型统一。我们提出错误。