Types OCaml详细类型错误
是否可以让OCaml显示有关类型错误的更多详细信息。比如说Types OCaml详细类型错误,types,compiler-errors,ocaml,Types,Compiler Errors,Ocaml,是否可以让OCaml显示有关类型错误的更多详细信息。比如说 Error: This expression has type AAAAA but an expression was expected of type BBBBB 有时,我会浪费大量精力试图找出哪些晦涩的语句期望BBBBB会导致这样的错误。如果它能显示有问题的行,那就太好了。适合我: $ cat miaou.ml let a = 1 == 'a';; $ ocamlc miaou.ml File "miaou.ml
Error: This expression has type AAAAA
but an expression was expected of type BBBBB
有时,我会浪费大量精力试图找出哪些晦涩的语句期望BBBBB会导致这样的错误。如果它能显示有问题的行,那就太好了。适合我:
$ cat miaou.ml
let a = 1 == 'a';;
$ ocamlc miaou.ml
File "miaou.ml", line 1, characters 13-16:
Error: This expression has type char but an expression was expected of type
int
可能您使用的是行号没有意义的交互式shell。是的,这是可能的。但是您需要与编译器进行一些协作,然后它将以更友好的错误响应您。因此,您的问题的答案是-使用类型注释。当您注释表达式时,您可以向编译器提供有关您意图的更多信息。然后,编译器可以向您显示更接近实际故障点的错误 例如: 您有一个正确的函数,该函数进行类型检查,但包含一个bug:
let run sum n lst =
List.fold ~init:(sum,n)
~f:(fun (s,n) x -> s + x, n + 1)
稍后,您尝试使用它时,它会在您身上溢出一个奇怪的错误:
let average lst =
let (sum,n) = run 0 0 lst in
sum / n;;
Characters 36-47:
let (sum,n) = run 0 0 lst in
^^^^^^^^^^^
Error: This expression has type int Core_kernel.Std.List.t -> int * int
but an expression was expected of type 'a * 'b
所以,你有麻烦了,你需要调查这个问题。您开始添加注释,本质上是向编译器解释您的意图。一段时间后,您将返回到run
的定义并添加注释:
let run sum n lst : int * int =
List.fold ~init:(sum,n)
~f:(fun (s,n) x -> s + x, n + 1)
并找出实际错误在这个函数中
所以,这里有一些规则,可以帮助您从编译器中获得更多信息性错误:
(非常复杂的类型)列表
,而不是'a列表
,或('a,'b类型)列表
。注意,这里的'a
和'b
不代表多态类型变量,这只是对编译器说的一种方式:“哦,我真的不知道,或者不在乎它们代表什么,只要随意用你想要的任何东西填充它就行了”,或者换句话说,你没有限制这种类型的类型检查器)let _ : int option = List.fold ...
merlin
。它将允许您在创建错误的那一刻捕获错误,而不是几个小时之后李>
最后一句话:OCaml typechecker只是一个约束解算器,如果你给它一组详细的约束,它会给你一个详细的答案。否则,对于错误的输入,它将给您一个错误的输出。Arthur Charguéraud为OCaml编译器编写了一个补丁,提供了更容易理解的错误消息。2014年ML车间的中对其进行了描述,相应代码为。要引用演示文稿中提供的示例,请键入
let rev_filter f l =
List.fold_left (fun x acc -> if f x then x::acc else acc) [] [1; 2; 3]
而不是经典的错误消息
Error: This expression has type 'a list
but an expression was expected of type 'a.
The type variable 'a occurs inside 'a list
诚然,这并不是很有帮助,你有一个新的:
Error: The function `List.fold_left' expects 3 arguments of types
['a -> 'b -> 'a] and ['a] and ['b list],
but it is given 3 arguments of types ['c -> 'c list -> 'c list]
and ['d list] and [int list].
这可以让你比较预期的和实际的参数类型,并希望理解你必须在
fun x acc->
中交换x
和acc
,而没有一点代码显示你认为编译器做得不好的地方,这只是一个咆哮,不是一个问题,utop甚至强调了错误发生的地方:-)是的,您的方法是最佳实践,可以解决我的问题,尽管我的印象是编译器必须有一些关于类型如何冲突的深入信息,为什么它不能只显示它们呢。在我的特殊情况下,它通常发生在重构函数时。如果一个函数从多个地方调用,并且还作为参数传递给其他函数。我不能只搜索函数名,因为它可以重命名为其他函数中的其他名称。编译器有一组约束,比如expr
应该有类型x
,在类型检查的过程中,他向集合中添加新的约束,直到它遇到两个相互矛盾的约束。这是一个类型错误,编译器只输出它们。编译器甚至不知道第一个约束是什么,以及后来添加了什么。它可能会暴露其他约束,但它只适用于非常小的程序。在很大程度上,这将造成更多的混乱。这将是有用的indeed@nlucaroni扰流板>
是否故意存在:因为问题是关于理解错误消息,我认为最好让读者自己搜索问题所在,以及第二条消息是否比第一条消息更有用。为什么此修补程序从未合并到核心中-(现在已经过时了,不能使用了。