Compiler construction 为什么在ocaml编译器源代码中打印Parsetree.implementation失败的数目?

Compiler construction 为什么在ocaml编译器源代码中打印Parsetree.implementation失败的数目?,compiler-construction,ocaml,Compiler Construction,Ocaml,此代码工作正常: let ()= let filename = "/home/wk/prog/LocationTest/b.ml" in Location.input_name := filename ; let readhandle = open_in filename in let buf = Lexing.from_channel readhandle in Location.init buf filename ; let ast = Parse.implementation

此代码工作正常:

let ()=
 let filename = "/home/wk/prog/LocationTest/b.ml" in
 Location.input_name := filename ;
 let readhandle = open_in filename in
 let buf = Lexing.from_channel readhandle in
 Location.init buf filename ;
 let ast = Parse.implementation buf in
 Printf.printf "%d" (List.length ast) ;
ast的类型是Parsetree.structure,它是“structure\u item list”,所以我可以使用list.length获取它的长度

我使用相同的方法调试ocaml 4.07编译器源代码:

我更改了ocaml 4.07编译器源代码/driver/pparse.ml 181-183:

let lexbuf = Lexing.from_channel ic in
Location.init lexbuf inputfile;
Profile.record_call "parser" (fun () -> parse_fun lexbuf)
为此:

let lexbuf = Lexing.from_channel ic in
Location.init lexbuf inputfile;
let xx=parse_fun lexbuf in
Printf.printf "%d" (List.length xx);
Profile.record_call "parser" (fun () -> xx)
parse_的乐趣是parse.implementation,然后是“make world”,得到错误:

Error: This expression has type 'a list
   but an expression was expected of type a

我不知道为什么在这种情况下同样的方法会失败,谢谢

首先,我可以建议您不要通过查看编译器代码库来学习OCaml吗?编译器的代码库中充满了旧的习惯用法、微妙的不变量、经过大量优化的算法,对于初学者来说,这些代码的文档记录非常少。因此,如果您正在努力使用OCaml,那么它通常不是一个学习的好地方

对于您手头的错误,问题在于
parse\u fun lexbuf
的结果不是
结构,而是本地抽象类型
a
。此局部抽象类型受
file\u aux
kind
参数约束。
kind
的类型是
ast\u kind
,它是一种广义抽象数据类型(又名GADT),定义为

type 'a ast_kind =
| Structure: structure ast_kind
| Signature: signature ast_kind
因此,
a
可以是结构或签名。这两个都是列表,但您需要向typechecker公开这一事实,以便能够计算列表长度:

let len (type a) (kind:a ast_kind) (l:a) = match kind with
| Signature -> List.length l
| Structure -> List.length l

完整的错误信息是什么?