Why does this Show instance in Haskell (Hugs) cause a stack overflow error?

508 views Asked by At

The following is a polymorphic data type in Haskell, interpreted by Hugs. I am trying to create an instance of Show for Equality.

The instance declaration says that if a type "a" is in Show, then Equality a is in Show. It should print the two arguments to the constructor Equals a b in the form "a = b".

data Equality a = Equals a a 

instance (Show a) => Show (Equality a) where
show (Equals a b) = a ++ " = " ++ b

Yet, typing something into Hugs like "(Equality 9 9)" yields:

ERROR - C stack overflow

So, I tried indenting the "show (Equals a b)..." line with a couple of spaces. I'm not sure what the difference would be, but was just playing around and then got this:

Inferred type is not general enough
*** Expression    : show
*** Expected type : Show (Equality a) => Equality a -> String
*** Inferred type : Show (Equality [Char]) => Equality [Char] -> String

Can anyone explain why these errors are occurring, or suggest a better way of implementing this show instance?

Thank you!

3

There are 3 answers

4
Erik Hinton On BEST ANSWER

The indenting does matter due to Haskell's at-times-strange whitespace sensitivity. Without the indent, the compiler cannot tell that the following statement belongs to the where.

The error that you are getting is because the polymorphic type, having no constraints, does not ensure that a and b can concatenated with the " = " string. What if you have Equals 1 1. How would you concatenate that without making the Ints strings first?

However, if you show a and b first, all works out because show martials the values into something that can be concatenated with a String.

data Equality a = Equals a a

instance (Show a) => Show (Equality a) where
    show (Equals a b) = (show a) ++ " = " ++ (show b)
0
franza On

I think your problem is that you didn't call function show on arguments a and b. I did this in GHC but I think it should work:

data Equality a = Equals a a 

instance (Show a) => Show (Equality a) where
  show (Equals a b) = show a ++ " = " ++ show b

Then:

> Equals 9 9
9 = 9
0
Mikhail Glushenkov On

Your code is indented incorrectly. It defines an empty Show instance:

instance (Show a) => Show (Equality a) where

and a separate top-level function show:

show (Equals a b) = a ++ " = " ++ b

of type Equality [Char] -> [Char]. So when you try to use your Show instance, the default definition of show from the Show class gets picked up. Looking at the code:

showsPrec _ x s = show x ++ s
show x          = showsPrec zeroInt x ""

you can see that the default show is defined in terms of showsPrec, which is in turn defined in terms of show. This explains why your program goes into an infinite loop.

To fix the code, indent it appropriately, and add missing calls to show to fix the type error (which stems from the fact that you can't concatenate an arbitrary type a with a string - you have to convert a to a string first):

data Equality a = Equals a a

instance (Show a) => Show (Equality a) where
  show (Equals a b) = show a ++ " = " ++ show b

Testing:

*Main> show (Equals 9 9)
"9 = 9"