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}
为什么编译器会抱怨?
不允许使用此表单,因为内联记录的类型可能会被转义。
你很可能想写一些变体
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 … }
更新此记录。