Interaction and ambiguous type variables
Ralf Hinze
ralf@informatik.uni-bonn.de
Thu, 3 Jul 2003 15:08:30 +0200
Dear all,
I am posting the following bug report every once in a while.
It describes a recurring and annoying problem (which I call
bug). It's annoying for beginners and students and it's
annoying for instructors, as well.
Here we go (using Hugs all along, but ghci is not that different).
------------------------------------------------------------------------------
<< Instructor:
implement `mirror' (aka reverse).
<< Student:
> mirror :: [a] -> [a]
> mirror [] = []
> mirror (a : as) = mirror as ++ [a]
But, I have a problem: the program does not work.
Main> mirror []
ERROR - Cannot find "show" function for:
*** Expression : mirror []
*** Of type : [a]
<< Instructor:
it's because `mirror []' has the polymorphic type `[a]' and the
compiler cannot determine the `Show' instance for `a'. You can
find further explanations at
http://www.cs.ukc.ac.uk/people/staff/sjt/craft2e/errors.html
[All this is jolly difficult to explain in the first week of
a Haskell course. It's annyoing because the result is, of course, the
empty list. Yes, I know that the empty list can be printed in
different ways depending on the type:
Main> mirror [] :: [Int]
[]
Main> mirror [] :: String
""
Alas, I don't think this justifies the trouble.]
<< Instructor:
implement `turn' (aka mirror or reverse) on trees.
<< Student:
> data Tree a = Empty | Node (Tree a) a (Tree a)
> deriving (Show)
> turn :: Tree a -> Tree a
> turn Empty = Empty
> turn (Node l a r) = Node (turn r) a (turn l)
But, I have a problem: the program does not work.
Main> turn Empty
ERROR - Cannot find "show" function for:
*** Expression : turn Empty
*** Of type : Tree a
<< Instructor:
<see above>
[Now, the result is obvious and there is only one way to print it!
Yes, I know that we can complicate matters slightly so that the
result is again ambiguous in print.
Main> turn (Node Empty [] Empty)
ERROR - Cannot find "show" function for:
*** Expression : turn (Node Empty [] Empty)
*** Of type : Tree [a]
Main> turn (Node Empty [] Empty) :: Tree [Int]
Node Empty [] Empty
Main> turn (Node Empty [] Empty) :: Tree String
Node Empty "" Empty
Again, it's only the empty list that may come out in different
shapes. But, things still can get worse.]
<< Instructor:
implement a test that checks whether a list is ordered.
<< Student:
> ordered :: (Ord a) => [a] -> Bool
> ordered [] = True
> ordered [a] = True
> ordered (a : b : as) | a <= b = ordered (b : as)
> | otherwise = False
But, I have a problem: the program does not work.
Main> ordered []
ERROR - Unresolved overloading
*** Type : Ord a => Bool
*** Expression : ordered []
<< Instructor:
<see above>
[Now, we have not even a problem of ambiguity. The expression is not
ambiguous.]
------------------------------------------------------------------------------
The general problem is that the expression submitted to Hugs or GHC has a
polymorphic type *or* that a subexpression has a polymorphic type (as
in the last example). A simple solution is to monomorphize the type
instantiating all type variables to, say, the empty type `Void'.
Additionally, we have to add instances for the standard classes
instance Show Void
instance Eq Void
etc.
Why do we need instances for all the classes? If a subexpression has
a polymorphic type, then other classes may be affected.
Main> [] == []
ERROR - Unresolved overloading
*** Type : Eq a => Bool
*** Expression : [] == []
------------------------------------------------------------------------------
Let me close by saying that I think it's important to address this
problem because it bites students again and again and again ...
Cheers, Ralf