Compiler errors 表单是不允许的,因为内联记录的类型可能会转义

Compiler errors 表单是不允许的,因为内联记录的类型可能会转义,compiler-errors,ocaml,record,Compiler Errors,Ocaml,Record,为什么编译器会抱怨 不允许使用此表单,因为内联记录的类型可能是 逃跑 你很可能想写一些 type 'a queue = Q of {estack : 'a list; dstack : 'a list} | Empty let enqueue d q = match q with | Empty -> Q {estack = [d]; dstack = []} | _ -> Q {q with estack = q.estack :: d} 编译器错误 不

为什么编译器会抱怨

不允许使用此表单,因为内联记录的类型可能是 逃跑

你很可能想写一些

type 'a queue = Q of {estack : 'a list; dstack : 'a list} | Empty

let enqueue d q = match q with  
    | Empty -> Q {estack = [d]; dstack = []}
    | _ -> Q {q with estack = q.estack :: d} 
编译器错误
不允许使用此表单,因为内联记录的类型可能转义
源于这样一个事实,即内联记录在OCaml中不完全是第一类对象。特别是,它们不能在构造函数的上下文之外使用。因此,当类型检查
Q{Q with…}
时,类型检查器试图将变量
Q
的类型与
Q
内联记录的类型统一起来,并引发错误,因为这种统一会将
Q
的内联记录泄漏给外部变量
Q

编辑:

由于您编辑的版本存在完全相同的问题,以下是 修正版

let enqueue d q = match q with  
| Empty -> Q {estack = d; dstack = []}
| Q r -> Q {r with estack = r.estack @ d} 
与以前一样,问题是在
Q{Q with…}
Q
中,类型为
'a enqueue
,而构造函数
Q
期望类型为
'a enqueue.Q.inlined_record
的变量作为参数;在OCaml表面语言中没有显式名称。因此,需要首先通过
qr
上的模式匹配提取内部记录,然后使用
Q{r with…}
更新此记录

let enqueue d q = match q with  
    | Empty -> Q {estack = [d]; dstack = []}
    | Q r -> Q {r with estack = d :: r.estack};;