OMG, I just spent twenty minutes trying to figure out a compiler error. I wrote my own version of List.filter
let filter pred =
let rec filter_acc acc = function
head::tail when predicate head -> filter_acc head::acc tail
| head :: tail -> filter_acc acc tail
| [] -> List.rev acc
in
filter_acc [];;
The bold variable above is identified as the source of the error and here is the message
Error: This expression has type ('a -> 'b) list but is here used with type 'a
What? acc is a list of functions that take 'a and return 'b, no it is simply 'a list.
After spending way too much time pondering this problem I finally accepted that I am a static type luddite and determined that if the type inference system can't make head nor tail of my code, I should give it a hint and see if the error changes. So in the function below I specify that the acc parameter to filter_acc is a list of some type
let filter pred =
let rec filter_acc (acc : 'a list) = function
head::tail when predicate head -> filter_acc head::acc tail
| head :: tail -> filter_acc acc tail
| [] -> List.rev acc
in
filter_acc [];;
Sure enough the error now concerns head::acc and the error changes to
Error: This expression is not a function, it cannot be applied
Aha, the compiler thinks I am attempting to use acc as a function (acc tail), the precedence of the cons operator is obviously very low.
The following corrects the problem:
let filter pred =
let rec filter_acc acc = function
head::tail when predicate head -> filter_acc (head::acc) tail
| head :: tail -> filter_acc acc tail
| [] -> List.rev acc
in
filter_acc [];;
Bear with it, if you find yourself in this situation pile on the type information and let the compiler help you identify, however, esoterically, where the real error lies.
Monday, April 13, 2009
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment