Подтвердить что ты не робот

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

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

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

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

или

read "(a b)" :: SomeType Char

произвести

(a b)

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

4b9b3361

Ответ 1

Здесь приведен пример, основанный на документации, который должен иметь возможность анализировать все, что show отображает (если тип имеет совместимый Read instance), то есть 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

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