如何在haskell中为数据类型创建Read实例

nob*_*ody 13 haskell typeclass

所以我有一个数据类型

data SomeType a =
    Type a |
    Mix (SomeType a) (SomeType a)
Run Code Online (Sandbox Code Playgroud)

这是SomeType的show实例

instance (Show a) => Show (SomeType a) where
    show (Type a) = show a
    show (Mix a b) = "(" ++ show a ++ " " ++ show b ++ ")"
Run Code Online (Sandbox Code Playgroud)

所以

Mix (Type 5) (Type 4)
Run Code Online (Sandbox Code Playgroud)

会给我的

(5 4)
Run Code Online (Sandbox Code Playgroud)

现在我想拥有

read "(3 4)" :: SomeType Int 
Run Code Online (Sandbox Code Playgroud)

生产

(3 4)
Run Code Online (Sandbox Code Playgroud)

要么

read "(a b)" :: SomeType Char
Run Code Online (Sandbox Code Playgroud)

生产

(a b)
Run Code Online (Sandbox Code Playgroud)

我迷失在如何使用Read类.

hvr*_*hvr 13

这是一个基于文档的示例,该文档应该能够解析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')
Run Code Online (Sandbox Code Playgroud)

从而,

> read "(3 4)" :: SomeType Int 
(3 4)
it :: SomeType Int
Run Code Online (Sandbox Code Playgroud)

但请注意,对于带有单引号的字符SomeType Char的默认Show实例Char:

> read "('a' ('b' 'c'))" :: SomeType Char
('a' ('b' 'c'))
it :: SomeType Char
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助