2011-04-02 70 views
20

我有一个自定义数据类型Foo = Foo{ a :: Int, b :: Int},我试图让Foo成为一个自定义的read实例。我已经有一个函数,我试着这样做:在Haskell中为自定义数据类型创建Read type类的实例

instance Read (Foo a b) where 
    read s = bar s 

但我发现了以下错误,当我在我的文件加载到GHCI来测试它:Fraction.hs:11:1: read' is not a (visible) method of class Read'

有人能告诉我是什么问题是,我怎么能实际实例化这种类型?

回答

18

Read类型类不直接声明read;相反,它定义了readsPrec,它支持优先级(这对于涉及其他类型元素的复杂数据类型的值时非常重要)。你当你使用deriving (Read)的定义看起来大致是

instance (Read a) => Read (Tree a) where 

    readsPrec d r = readParen (d > app_prec) 
        (\r -> [(Leaf m,t) | 
          ("Leaf",s) <- lex r, 
          (m,t) <- readsPrec (app_prec+1) s]) r 
        ++ readParen (d > up_prec) 
        (\r -> [(u:^:v,w) | 
          (u,s) <- readsPrec (up_prec+1) r, 
          (":^:",t) <- lex s, 
          (v,w) <- readsPrec (up_prec+1) t]) r 
     where app_prec = 10 
      up_prec = 5 

(这显然是一个Tree数据类型,但类似的规则适用于其它用户定义的抽象数据类型)。 (另外,上面是一个小小的谎言:GHC实际上使用了不同的实现方式,但是除非您愿意在GHC内部进行挖掘,否则上述是您应该做的一件事。)

read以术语定义readsPrecreadListRead中的另一种方法,除Char之外的每种类型都默认为[Char],其中[Char]用作字符串而不是Char的列表)。

如果标准推导不充分,对于类似于您的类型,它只是一个Int s桶,您可以忽略优先级参数。

BTW,ReadShow相当慢;您可能需要考虑其他方式来处理数据的I/O。

+11

你有任何关于阅读和展示替代品的建议吗? – user381261 2011-04-02 23:08:43

3

这是因为您可能要实现的类方法是readsPrec。在这里看到的阅读类型类的完整信息:http://zvon.org/other/haskell/Outputprelude/Read_c.html

BTW,你应该能够只使用自动推导和编译器将这些实例化阅读方法你,例如:

data Foo = Foo Int Int 
      deriving (Read, Show) 
+1

我知道我可以做到这一点,但我不太喜欢读取自动完成的方式,因为它不那么直观,想要制作更好的版本。 – user381261 2011-04-02 03:53:06

相关问题