2013-11-25 42 views

回答

1

Read,Show,Eq和朋友是typeclasses。基本上它們是可以實現某些功能的接口,如show,read,==等等。你提到的兩個,ShowRead定義了你的類型的兩個函數。

read :: String -> YourType 
show :: YourType -> String 

事實上,其實際作用是產生一個類型類的實例,讓您使用readshow因爲如果他們有這些類型。

deriving處理這件事通常不錯,因爲它只是樣板,常常用於調試。通常你只是想打印出來,deriving Show給你一個很好的方法來做到這一點。

實質上,deriving只是讓編譯器爲您生成代碼的一種方式。這對於EqOrdBounded尤其有用,您可以輕鬆地創建一個微不足道的錯誤,該錯誤非常難以調試。

4

當您定義自己的數據類型時,通常會有大量的樣板類的樣板代碼,您並不想自行編寫代碼。編譯器通常可以爲你解決這個問題。

舉例來說,如果你有型

data Direction = North | South | East | West 

你不會是能夠做到

if direction == North then ... 

因爲你還沒有書面的Eq實例爲Direction。你可以寫

instance Eq Direction where 
    North == North = True 
    South == South = True 
    East == East = True 
    West == West = True 
    _  == _  = False 

但是這6行額外的代碼,真的不幫你或別人理解你的代碼。類似Show,Ord,Enum,Bounded,Bounded,ReadFunctor等類,這些都需要寶貴的時間和精力來編寫,因爲編譯器自己弄清楚它們是非常微不足道的。這就是deriving條款出現的地方。我提到的所有類型類都是可導出的(儘管Functor需要GHC中的DeriveFunctor擴展名),並且還有其他一些類。它所做的就是指示編譯弄清楚這些類型類本身的實現,所以

data Direction = North | South | East | West 
    deriving (Eq, Ord, Enum, Bounded, Show, Read) 

會產生大量的代碼,你可以自己,但沒有多少樂趣這樣做。如果需要,您可以看到通過使用-ddump-deriv標誌進行編譯生成的代碼,但它不會很漂亮,因爲它是編譯器生成的。

2

實例派生是Haskell中的一個強大功能,它使編譯器自動爲您創建的類型創建一些類型類的合理實例。通常情況下,對於EqOrd,Show,ReadEnumBounded之類的東西,編譯器可以猜測這些東西是合理的默認實例。例如,Eq有限和類型。

​​

從而推導減少了大量的樣板什麼時候適合。共獲得被認爲是Haskell中的核心功能和它既有被編譯器擴展像GeneralizedNewtypeDerivingDeriveFunctorDeriveFoldableDeriveTraversableDeriveGeneric,並DeriveDataTypeable延伸,並通過使用Generics導出和TemplateHaskell自動生成實例社區涵蓋。

舉例來說,如果你使用aeson哈斯克爾-JSON數據綁定庫,你會經常看到的模板哈斯克爾

deriveJSON ''MyType 

自動創建兩個ToJSONFromJSON實例。

綜合起來,這些都是確保只有代碼中最重要和特定部分必須寫入的方法。派生實例往往是「最簡單的可能實例」,因此可能具有最少的令人驚訝的行爲。與這些默認值相比較小的偏差可以在它們形成功能的基礎層之後被更直接地編碼。

+0

忘記了DeriveGeneric – jozefg

+0

是的 - 我現在加了! –