Haskell:读取多态数据类型和元组的实例

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 实例始终 returns "" 其余部分,这意味着它会丢弃其读取的值结束后的所有字符。在这里,悬空的 ) 表示元组的结束:无法解析元组,因为您丢弃了那个字符。

您需要使用您正在解析的对象的 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, "")]