ocaml - 如何在 OCaml 中解释此 GADT 错误?
问题描述
抱歉,这里有“我在这里错过了什么”的问题风格,但我只是在这里遗漏了一些东西。
我试图了解 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
;;
它工作正常。
更新(更多上下文):
- Ocaml 版本:
4.08.1
- 本次会议期间开放的图书馆:
Base
更新(解决方案):
- 结果是(如所选答案的第一行所述),因为我之前在
utop
运行中open Base ;;
- 在新的会话中,我能够输入最初提到的类型并且
eval
对此感到满意。
解决方案
错误的直接原因是您使用的库(可能是 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 -> int
的类型进行比较,并输出您的原始错误消息:eval a
$Lt_'a
Line 4, characters 15-23:
Error: This expression has type $Lt_'a but an expression was expected of type
int
推荐阅读
- spring - RestTemplate 中的 ResponseEntity 问题
- r - 在 pl/r 中传递一个向量作为参数来启动一个 for 循环
- php - Laravel 循环遍历关联数组然后保存到数据库
- php - Laravel - 在数据库的列中显示选定的 ID
- python - 在递归函数中跟踪和更新值
- regex - 正则表达式 - 排除以多次出现开头的字符串
- go - Goroutines 选择范围循环
- python-3.x - 使用带有特定数据表的 python 美丽的汤 urllib 网络抓取数据
- tensorflow - Tensorflow Lite:ResNet 示例模型在使用 ImageNet 进行验证期间给出了非常差的结果
- javascript - React:将函数作为道具传递但窗口未定义