Как создать экземпляр Read для типа данных в haskell

Итак, у меня есть тип данных

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

Это мой экземпляр шоу для 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)

дал бы мне

(5 4)

Теперь я хочу иметь

read "(3 4)" :: SomeType Int 

производить

(3 4)

or

read "(a b)" :: SomeType Char

производить

(a b)

Я не понимаю, как использовать класс Read.


person nobody    schedule 21.10.2011    source источник
comment
кстати, ваш пример для SomeType Char - это не то, что сгенерировало бы show (Mix (Type 'a') (Type 'b')).   -  person hvr    schedule 21.10.2011
comment
Вы можете получить оба экземпляра — Show и Read — с помощью deriving (Show, Read) после описания типа. Хотя они не будут производить ваши выходные и вводные данные, они являются стандартным способом отображения (а иногда и чтения) значений, поэтому вы должны использовать их вместо своих собственных экземпляров. Если вы хотите показать их по-другому, используйте отдельную функцию и назовите ее render или около того.   -  person bzn    schedule 21.10.2011


Ответы (1)


Вот пример, основанный на документации , который должен иметь возможность анализировать все, что отображает show (при условии, что для типа определен совместимый экземпляр Read), то есть read . show должен быть более или менее тождественным:

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

Таким образом,

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

Но обратите внимание, что для SomeType Char экземпляр Show по умолчанию для Char окружает символ одинарными кавычками:

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

надеюсь это поможет

person hvr    schedule 21.10.2011
comment
@Qin d - это приоритет оператора (который я случайно увеличил - я отредактировал это) окружающего контекста синтаксического анализа, а r - это текущая оставшаяся строка для анализа. - person hvr; 22.10.2011