是否可以让OCaml显示有关类型错误的更多详细信息。例如
Error: This expression has type AAAAA
but an expression was expected of type BBBBB
有些时候我浪费了大量精力试图弄清楚哪些晦涩的陈述期望BBBBB造成这样的错误。如果它可以显示有问题的行,那就太好了。
答案 0 :(得分:2)
是的,有可能。但是您需要与编译器进行一些协作,然后它会以更友好的错误响应您。所以你的问题的答案是 - 使用类型注释。当您注释表达式时,您可以为编译器提供有关您的意图的更多信息。然后编译器可以向您显示更接近实际故障点的错误。
示例:
你有一个功能,即类型检查,但包含一个错误:
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)
并发现实际错误在此函数内。
所以,有一些规则可以帮助你从编译器中获得更多信息错误:
注释顶级表达式(如果不喜欢指定它们,可以省略一些细节,以便代码仍然可读。例如,您可以编写{而不是(very * complex types) list
。 {1}}或'a list
。请注意,此处('a, 'b types) list
和'a
不代表多态类型变量,这只是对编译器的一种说法:“哦,我真的不知道,或者不关心它们代表什么,只要随意填写你想要的任何东西,或者换句话说,你不会限制这种类型的类型检查器。
始终注释通配符。如果您有这样的事情:
让_ = List.fold ...
然后确保这些通配符实际上符合您的想法:
'b
let _ : int option = List.fold ...
。它允许您在创建错误时捕获错误,而不是几个小时之后。 最后一句话:OCaml类型检查器只是一个约束求解器,如果你给它一组详细的约束,它会给你一个详细的答案。否则,对于输入错误,它会给你带来不好的输出。
答案 1 :(得分:0)
ArthurCharguéraud为OCaml编译器编写了一个补丁,提供了更易于理解的错误消息。它在2014年ML研讨会的this article中进行了描述,相应的代码为on github。如果您输入
,请引用演示文稿中提供的示例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].
可让您比较参数的预期和实际类型,并希望了解您必须在x
acc
和fun x acc ->
答案 2 :(得分:-1)
为我工作:
$ 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,其中行号没有意义。