
John Hughes writes:
One way to approach it is to write type signatures, but when a definition doesn't type check, remove the signature on that one and see whether it then typechecks. If so, the definition is right, but your type signature is wrong. Use ghci to find out the correct type signature, and insert it.
Another useful trick when chasing type errors is to stub out a few functions or cases of functions with 'undefined'. At first sight, 'undefined' is a fairly useless function since it always fails. But undefined has one great property: it's type is 'forall a. a' which means you can use it absolutely anywhere. Suppose I have 10 mutually recursive functions (e.g., an interpreter for a language) and I'm chasing a type error. I might comment out the real definition of some of the functions and replace them with definitions like: evalExpression :: <whatever type it should have> evalExpression = undefined {- real but possibly buggy definition goes here -} or I might comment out just some cases of a function while I figure out which branch is really causing the problem: evalExpression :: Env -> Expr -> Value evalExpression env (Int i) = IntValue i evalExpression env (Str s) = StringValue i evalExpression env (Apply f e) = undefined -- app (evalFunction env f) (evalExpression env e) evalExpression env (Var v) = undefined -- fromJust (lookup env v) -- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/