In the following Haskell code, the function typeError doesn't typecheck.
wrap x = [x]
listf :: [[a]] -> [[a]]
listf = id
typeCheck :: [a] -> [[a]]
typeCheck x = listf (wrap x)
typeError :: [a] -> [[a]]
typeError = wrap . listf
GHC produces this error if it's uncommented:
Couldn't match type `a' with `[a0]'
`a' is a rigid type variable bound by
the type signature for typeError :: [a] -> [[a]] at tim.hs:10:1
Expected type: [a] -> [a]
Actual type: [[a0]] -> [[a0]]
In the second argument of `(.)', namely `listf'
In the expression: wrap . listf
I don't understand why. a
should be able to unify with [a0]
- they are independent type variables. This is exactly the type it infers for for typeCheck
- but not when the .
operator is used.
Hugs produces a very similar, and similarly spurious, error message:
ERROR "repro.hs":10 - Inferred type is not general enough
*** Expression : typeError
*** Expected type : [a] -> [[a]]
*** Inferred type : [[a]] -> [[[a]]]
Furthermore, this works fine:
listf' :: [a] -> [a]
listf' = id
typeCheck' :: [a] -> [[a]]
typeCheck' = wrap . listf'
The problem only occurs with an [[a]] or [[[a]]] or greater. What's the deal here?
You seem to have reversed the function composition here.
-- This
typeCheck :: [a] -> [[a]]
typeCheck x = listf (wrap x)
-- is the same as
typeCheck' :: [a] -> [[a]]
typeCheck' = listf . wrap
-- while this
typeError :: [a] -> [[a]]
typeError = wrap . listf
-- is the same as
typeError' :: [a] -> [[a]]
typeError' x = wrap (listf x)
Now it should hopefully be obvious why this doesn't work. listf
requires that its argument is [[a]]
, but the signature of typeError
claims that it works for any [a]
.