让我们说我有一个框架的多态数据类型:
data Frame a = Frame {
fdata :: V.Vector (V.Vector a)
, frows :: Int
, fcols :: Int
}
makeFrame :: [[a]] -> Frame a
makeFrame s = ...
我希望它的文本表示看起来就像一个列表列表:
instance Show a => Show (Frame a) where
show (Frame m _ _) = show $ V.toList $ V.toList <$> m
instance Read a => Read (Frame a) where
readsPrec _ value = [makeFrame $ read value, "")]
我对我的阅读功能感到非常满意,直到我发现当一个帧在元组内部时它不能正常工作:
-- works
> let x = read $ show $ makeFrame [[1,2], [3,4]] :: Frame Int
> :t x
x :: Frame Int
-- doesn't work
> read $ show $ (1, makeFrame [[1,2], [3,4]]) :: (Int, Frame Int)
*** Exception: Prelude.read: no parse
-- meanwhile
> let x = read $ show $ (1, makeFrame [[1,2], [3,4]]) :: (Int, [[Int]])
> :t x
x :: (Int, [[Int]])
为什么无辜地将我的数据类型嵌入元组会以某种方式改变整个事物的解析方式?我错过了什么?
更新
以防万一,工作阅读实施:
instance Read a => Read (Frame a) where
readsPrec d v = do (lst, rst) <- readsPrec d v
return (makeFrame lst, rst)
答案 0 :(得分:5)
您的readsPrec
实例总是返回""
的剩余部分,这意味着它会在读取的值结束后丢弃所有字符。在这里,这是表示元组关闭的悬空)
:无法解析元组,因为你扔掉了那个角色。
您需要使用正在解析的事物的readsPrec
实例,以了解它消耗了多少个字符。我会使用比你更简单的新类型,以便可以编译而没有外部依赖:
newtype Wrapper a = Wrapper a
instance Show a => Show (Wrapper a) where
show (Wrapper x) = 'w':show x
instance Read a => Read (Wrapper a) where
readsPrec n ('w':s) = [(Wrapper x, r) | (x, r) <- readsPrec n s]
这样可行,但是如果我用类似于你的实例替换我的Read
实例,我会得到同样的错误:它在另一个数据结构内部时无法解析。
-- totally broken instance
instance Read a => Read (Wrapper a) where
readsPrec _ ('w':s) = [(Wrapper $ read s, "")]