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

问题描述 投票:1回答:1
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} 

为什么编译器会抱怨?

不允许使用此表单,因为内联记录的类型可能会被转义。

compiler-errors ocaml record
1个回答
2
投票

你很可能想写一些变体

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

编译器错误This form is not allowed as the type of the inlined record could escape源于内联记录不完全是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 = d :: r.estack};; 

和以前一样,问题是在Q { q with … }q有类型'a enqueue而构造函数Q期望作为参数'a enqueue.Q.inlined_record类型的变量;在OCaml表面语言中没有明确的名称。因此需要首先通过Q r上的模式匹配提取内部记录,然后使用Q { r with … }更新此记录。

© www.soinside.com 2019 - 2024. All rights reserved.