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

如何在OCaml中解释这个GADT错误?,ocaml,gadt,Ocaml,Gadt,对不起,这里的问题是“我遗漏了什么”,但我只是遗漏了一些东西 我试图理解GADT如何在OCaml中工作,我定义了以下内容(在utop): 我定义了一个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) &

对不起,这里的问题是“我遗漏了什么”,但我只是遗漏了一些东西

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

我定义了一个
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)
;;
这到底是什么意思?

为了进一步测试,我将表达式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
;;
它很好用

更新(更多上下文):

  • Ocaml版本:
    4.08.1
  • 在此会话期间打开的库:
    Base
更新(解决方案):

  • 结果是(如所选答案的第一行所述),因为我以前在
    utop
    run
    openbase
  • 在新的会话中,我能够输入最初提到的类型,
    eval
    对此感到满意

导致错误的直接原因是您使用的库(可能是Base或Core?)会隐藏多态比较运算符(
),并用整数比较运算符替换它们

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

| Lt (a, b) -> (eval a) < (eval b)
存在一个量化类型变量:
'a

Lt
上进行模式匹配时,需要将此类型变量替换为 一种新型的。此外,在错误消息中,尝试拾取是非常有用的 此类型的有意义名称。为此,typechecker构造一个 新类型的名称为
$
+
Lt
+
'a

  • $
    :标记存在类型
  • Lt
    :表示它是由构造函数引入的
    Lt
  • a
    :记住存在类型变量在构造函数的定义中被命名为
    'a
换句话说,在上面的模式匹配中,我们有一些类似于

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

该错误的直接原因是您使用的库(可能是Base或Core?)对多态比较运算符(
)进行了阴影处理,并将其替换为整数比较运算符

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

| Lt (a, b) -> (eval a) < (eval b)
存在一个量化类型变量:
'a

Lt
上进行模式匹配时,需要将此类型变量替换为 一种新型的。此外,在错误消息中,尝试拾取是非常有用的 此类型的有意义名称。为此,typechecker构造一个 新类型的名称为
$
+
Lt
+
'a

  • $
    :标记存在类型
  • Lt
    :表示它是由构造函数引入的
    Lt
  • a
    :记住存在类型变量在构造函数的定义中被命名为
    'a
换句话说,在上面的模式匹配中,我们有一些类似于

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

等等,这是因为我在评估中使用了
=
,并且这些限制为
int
?我无法在4.02.3或4.08.1上复制。您使用的是哪个版本?等等,这是因为我在评估中使用了
=
,并且这些限制为
int
?我无法在4.02.3或4.08.1上复制。你是哪个版本的?
| Lt ( (a: $Lt_'a eval), (b: $Lt_'a eval)) -> (eval a) < (eval b)
  (eval a) < (eval b)
 Line 4, characters 15-23:
 Error: This expression has type $Lt_'a but an expression was expected of type
     int