This code is from the book "Learn You a Haskell for Great Good!":
maximum' :: (Ord a) => [a] -> a
maximum' [] = error "maximum of empty list"
maximum' [x] = x
maximum' (x:xs)
| x > maxTail = x
| otherwise = maxTail
where maxTail = maximum' xs
It works fine on non-empty lists, but supplying an empty list:
main = print $ maximum' []
gives this compiler error:
Ambiguous type variable ‘a0’ arising from a use of ‘maximum'’ prevents the constraint ‘(Ord a0)’ from being solved.
Why is that? Shouldn't the code actually catch it when an empty list is supplied? I don't understand the error message.
CodePudding user response:
Ambiguous type variable ‘a0’ arising from a use of ‘maximum'’ prevents the constraint ‘(Ord a0)’ from being solved.
This means that when you call maximum' []
, the type of []
is not clear: it could be [Int]
or [()]
or something else.
In this particular case, the result happens to be the same. The compiler can't prove it here, and in general that's not the case. Consider this function:
readAndPrepend :: (Read a, Show a) => String -> [a] -> String
readAndPrepend s xs = show (read s : xs)
If you call readAndPrepend "42" []
, it's ambiguous what the result should be:
ghci> readAndPrepend "42" ([] :: [Int])
"[42]"
ghci> readAndPrepend "42" ([] :: [Double])
"[42.0]"
ghci> readAndPrepend "42" ([] :: [()])
"[*** Exception: Prelude.read: no parse
ghci>
In other words, the a
type variable is "unsolved", like a free x
in a mathematical equation.
What you need to do is pick a type that you want the list to be and specify it explicitly:
main = print $ maximum' ([] :: [()])