2011-04-02 68 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

相關問題