简体   繁体   中英

How to create instance of Read for a datatype in haskell

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.

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 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM