14

So I have a data type

data SomeType a =
    Type a |
    Mix (SomeType a) (SomeType a)

This my show instance for SomeType

instance (Show a) => Show (SomeType a) where
    show (Type a) = show a
    show (Mix a b) = "(" ++ show a ++ " " ++ show b ++ ")"

So

Mix (Type 5) (Type 4)

would give me

(5 4)

Now I want to have

read "(3 4)" :: SomeType Int 

produce

(3 4)

or

read "(a b)" :: SomeType Char

produce

(a b)

I am lost at how to use the Read class.

alternative
  • 12,703
  • 5
  • 41
  • 41
nobody
  • 2,709
  • 6
  • 35
  • 37
  • btw, your example for `SomeType Char` is not what `show (Mix (Type 'a') (Type 'b'))` would have generated. – hvr Oct 21 '11 at 15:45
  • 2
    You can derive both - the Show and Read instance - with a `deriving (Show, Read)` after the type delcaration. While they won't produce your output and input, they are a standard way of showing (and sometimes reading) values, which is why you should use them instead of your own instances. If you want to show them in a different way, use a separate function and call it `render` or so. – bzn Oct 21 '11 at 15:59

1 Answers1

13

Here's an example based on the documentation which should be able to parse everything that show renders (assuming the type has a compatible Read instance defined), that is read . show should be more or less the identity:

instance (Read a) => Read (SomeType a) where
    readsPrec d r = readMix r ++ readType r
      where
        readMix = readParen True $ \r -> do
            (v1, r'') <- readsPrec d r
            (v2, r')  <- readsPrec d r''
            return (Mix v1 v2, r')

        readType r = do
            (v, r') <- readsPrec d r
            return (Type v, r')

Thus,

> read "(3 4)" :: SomeType Int 
(3 4)
it :: SomeType Int

But note, that for SomeType Char the default Show instance of Char surrounds the character with single quotes:

> read "('a' ('b' 'c'))" :: SomeType Char
('a' ('b' 'c'))
it :: SomeType Char

hope this helps

hvr
  • 7,775
  • 3
  • 33
  • 47
  • 1
    @Qin `d` is the operator precedence (which I accidentally incremented -- I've edited this) of the enclosing parsing context and `r` is the current remaining string to be parsed. – hvr Oct 21 '11 at 21:02