OCaml详细类型错误

时间:2014-11-18 09:51:17

标签: types compiler-errors ocaml

是否可以让OCaml显示有关类型错误的更多详细信息。例如

Error: This expression has type AAAAA
       but an expression was expected of type BBBBB

有些时候我浪费了大量精力试图弄清楚哪些晦涩的陈述期望BBBBB造成这样的错误。如果它可以显示有问题的行,那就太好了。

3 个答案:

答案 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)

并发现实际错误在此函数内。

所以,有一些规则可以帮助你从编译器中获得更多信息错误:

  1. 注释顶级表达式(如果不喜欢指定它们,可以省略一些细节,以便代码仍然可读。例如,您可以编写{而不是(very * complex types) list。 {1}}或'a list。请注意,此处('a, 'b types) list'a不代表多态类型变量,这只是对编译器的一种说法:“哦,我真的不知道,或者不关心它们代表什么,只要随意填写你想要的任何东西,或者换句话说,你不会限制这种类型的类型检查器。

  2. 始终注释通配符。如果您有这样的事情:

    让_ = List.fold ...

  3. 然后确保这些通配符实际上符合您的想法:

    'b
    1. 使用let _ : int option = List.fold ... 。它允许您在创建错误时捕获错误,而不是几个小时之后。
    2. 最后一句话: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

中交换accfun 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,其中行号没有意义。