我如何解释 OCaml 中的这个 GADT 错误?

How do I interpret this GADT error in OCaml?

抱歉 "what am I missing here" 问题的风格,但我在这里遗漏了一些东西。

我试图了解 GADT 在 OCaml 中的工作原理,我定义了以下内容(在 utop 中):

 type value =
| Bool : bool -> value
| Int : int -> value
;;

type _ value =
| Bool : bool -> bool value
| Int : int -> int value
;;

type _ expr =
| Value : 'a value -> 'a expr
| If : bool expr * 'a expr * 'a expr -> 'a expr
| Lt : 'a expr * 'a expr -> bool expr
| Eq : 'a expr * 'a expr -> bool expr
| Gt : 'a expr * 'a expr -> bool expr
;;

我定义了一个eval函数:

let rec eval : type a. a expr -> a = function
| Value (Int i) -> i
| Value (Bool b) -> b
| Lt (a, b) -> (eval a) < (eval b)
| Gt (a, b) -> (eval a) > (eval b)
| Eq (a, b) -> (eval a) = (eval b)
| If (c, a, b) -> if eval c then (eval a) else (eval b)
;;

但出现错误:

Line 4, characters 15-23:
Error: This expression has type $Lt_'a but an expression was expected of type
         int

这到底是什么意思?

为了进一步测试,我将表达式 GADT 修改为:

type _ expr =
| Value : 'a value -> 'a expr
| If : bool expr * 'a expr * 'a expr -> 'a expr
| Lt : int expr * int expr -> bool expr
| Eq : 'a expr * 'a expr -> bool expr
| Gt : int expr * int expr -> bool expr
;;

然后我看到了

Line 6, characters 15-23:
Error: This expression has type $Eq_'a but an expression was expected of type
         int

当我最后修改为

type _ expr =
| Value : 'a value -> 'a expr
| If : bool expr * 'a expr * 'a expr -> 'a expr
| Lt : int expr * int expr -> bool expr
| Eq : int expr * int expr -> bool expr
| Gt : int expr * int expr -> bool expr
;;

它工作正常。

更新(更多上下文):

更新(解决):

错误的直接原因是您使用的库(可能是 Base 或 Core?)隐藏了多态比较运算符(<<==>=,>) 并将它们替换为整数比较运算符。

关于错误消息,当您对具有存在类型的 GADT 构造函数进行模式匹配时,

| Lt (a, b) -> (eval a) < (eval b)

类型检查器引入了新类型来表示存在类型。 这里,在 Lt

的(原始)定义中
| Lt : 'a expr * 'a expr -> bool expr

有一个存在量化类型变量:'a.

Lt上进行模式匹配时,我们需要将这个类型变量替换为 一种新类型。此外,在错误消息中尝试选择是非常有用的 这种类型的有意义的名称。为此,类型检查器构造了一个 一个接一个地命名为 $ + Lt + 'a:

  • $: 标记存在类型
  • Lt:表示由构造函数引入Lt
  • a:要记住存在类型变量在构造函数的定义中被命名为'a

换句话说,在上面的模式匹配中,我们有类似于

的东西
| Lt ( (a: $Lt_'a eval), (b: $Lt_'a eval)) -> (eval a) < (eval b)

输入时:

  (eval a) < (eval b)

类型检查器比较 < 的类型:int -> inteval a 的类型:$Lt_'a 并输出原始错误消息:

 Line 4, characters 15-23:
 Error: This expression has type $Lt_'a but an expression was expected of type
     int