简体   繁体   中英

OCaml verbose type error

Is it possible to have OCaml show more detail on type error. For example

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

There are times when I waste a lot of energy trying to figure out which obscure statements expect BBBBB causing such error. It would be nice if it can display the problematic lines.

Yes, it is possible. But you need a bit of collaboration with a compiler, and then it will respond to you in a more friendly error. So the answer to your question is - use type annotations. When you annotate expressions, you give a compiler more information on your intentions. And then compiler can show you the error that is much closer to the actual point of failure.

Example:

You have right a function, that typechecks, but contains a bug:

let run sum n lst = 
    List.fold ~init:(sum,n)
              ~f:(fun (s,n) x -> s + x, n + 1)

later, you're trying to use it and it spills a strange error on you:

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

So, you're in trouble, and you need to investigate the problem. You start to add annotations, essentially explaining to a compiler your intentions. Some time after, you will return to your definition of run and add an annotation:

let run sum n lst : int * int = 
    List.fold ~init:(sum,n)
              ~f:(fun (s,n) x -> s + x, n + 1)

And find out that the actual error is inside this function.

So, there're some rules, that will help you to get a much more informative errors from compiler:

  1. Annotate top-level expressions (you can omit some details, if don't like to specify them, so that the code is still readable. For example, instead of (very * complex types) list , you can write 'a list , or ('a, 'b types) list . Note, here 'a and 'b don't stand for polymorphic type variables, this is just a way to say to compiler: "Oh, I really don't know, or don't care what they stand for, just feel free to fill it with whatever you want", or in other words, you're not constraining a type-checker on this types).

  2. Always annotate wildcards. If you have something like this:

    let _ = List.fold ...

Then make sure that this wildcards stands actually for what you're thinking of them:

let _ : int option = List.fold ...
  1. Use merlin . It will allow you to catch errors in the moment you've created them, not several hours later.

Last words: the OCaml typechecker is just a constraint solver, and if you give it a detailed sets of constraints it will give you back a detailed answer. Otherwise, for bad input it will give you a bad output.

Arthur Charguéraud has written a patch for the OCaml compiler that provides easier to understand error messages. It is described in this article from the 2014 ML Workshop and the corresponding code is on github . To quote an example provided in the presentation, if you type

let rev_filter f l =
  List.fold_left (fun x acc -> if f x then x::acc else acc) [] [1; 2; 3]

instead of having the classical error message

Error: This expression has type 'a list
       but an expression was expected of type 'a.
       The type variable 'a occurs inside 'a list

which admittedly is not very helpful, you have this new one:

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].

which let you compare the expected and actual types of the arguments and hopefully understand that you have to swap x and acc in fun x acc ->

Work for me :

$ 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

maybe you are using the interractive shell where line number don't have meaning.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM