3

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!

Cody
  • 135
  • 1
  • 3
  • 11
  • This is a bad idea in general: `Show` is meant to provide a basic serialisation mechanism for Haskell, producing valid Haskell code (modulo import details). If you want to do custom output formatting, then produce a custom `prettyPrint :: a -> String` function or similar, possibly using a pretty-printing library for complex outputs. – ivanm Oct 23 '11 at 03:09

3 Answers3

3

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"
Mikhail Glushenkov
  • 14,928
  • 3
  • 52
  • 65
1

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
franza
  • 2,297
  • 25
  • 39
1

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)
Erik Hinton
  • 1,948
  • 10
  • 15
  • Ah. I danced around that for a while but couldn't put it all together. Thank you for the clear, detailed, and exampled response. – Cody Oct 22 '11 at 23:52
  • 2
    You can safely eliminate the parens around `(show a)` and `(show b)` – Dan Burton Oct 23 '11 at 00:10
  • 2
    I wouldn't say that the indentation rules are strange... if this line belongs to something, indent it more! – ivanm Oct 23 '11 at 03:08
  • I guess I mean that they are "at first blush" strange. Ha. It took me a few days to feel completely comfortable with when I had to indent, when I had to indent past an equal sign etc. But by this measure (that of my slow grokking) much of Haskell is strange. But good strange! – Erik Hinton Oct 23 '11 at 03:13