[英]Haskell: read instance for polymorphic data type and tuples
假设我有一个框架的多态数据类型:
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)
您的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
实例替换Read
实例,则会遇到相同的错误:它无法在另一个数据结构中解析。
-- totally broken instance
instance Read a => Read (Wrapper a) where
readsPrec _ ('w':s) = [(Wrapper $ read s, "")]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.