2012-08-06 46 views
2

我正在尋找一些關於以下代碼的重構/最佳實踐建議。我想盡量避免擴展,同時爲不同的「版本」保持獨立的模塊,這些模塊是互斥的。我目前的解決方案是使用一個類並使用存在性量化爲每個CountrySets創建一個通用類型。Haskell重構建議

如果我使用面向對象的方式,這對我來說很容易完成,但是我無法想到「功能」。

謝謝你的時間。

Province.hs

{-# LANGUAGE ExistentialQuantification, RankNTypes #-} 
module Province where 

    class Country a where 
    --some stuff that is not important 

    data Power = 
    forall a. (Show a, Eq a, Country a) => Power a | 
    Netural | 
    Water 

    data Unit = Unit { 
    power :: forall a. (Show a, Eq a, Country a) => a, 
    piece :: Piece 

    data Piece = Tank | Plane 

    data Province = Province { 
    power :: Power, 
    provName :: String 
    } deriving (Eq) 

    instance Show Power where 
    show (Power b) = "Power " ++ show b 
    show (Netural) = "Netural" 
    show (Water) = "Water" 

    instance Eq Power where 
    (==) a b = Prelude.show a == Prelude.show b 

Version1.hs

import Province 

    data CountrySet1 = 
    Country11 | 
     Country12 
    deriving (Eq, Show) 
    instance Country CountrySet1 where 

    provs = 
    one1:one2:[] 

    one1 = Province (Power Country11) "Place11" 
    one2 = Province (Power Country12) "Place12" 

Version2.hs

import Province 

    data CountrySet2 = 
    Country21 | 
    Country22 
     deriving (Eq, Show) 
    instance Country CountrySet2 where 

    provs = 
    two1:two2:[] 

    two1 = Province (Power Country11) "Place21" 
    two2 = Province (Power Country12) "Place22" 
+3

我認爲這是[代碼評論](http://codereview.stackexchange.com/)網站的好選擇。但是,我不會自己使用它,所以我不能100%確定它符合他們的標準。 – 2012-08-06 21:30:29

+1

我會在那裏發佈,看看我得到了什麼。 – 2012-08-06 21:38:33

回答

7

你不必把類構造函數在數據類型中您可以參數化,而不是在a可變數據類型,這樣就可以將制約該類型的類實例自己,就像這樣:

-- Note that I added a type variable to "Power" 
data Power a = Power a | Neutral | Water 

instance (Show a) => Show (Power a) where ... 

instance (Eq a) => Eq (Power a) where ... 

...或者你可以做大多數人一樣,用deriving

data Power a = Power a | Neutral | Water deriving (Eq, Show) 

這會產生你寫的完全一樣的情況下(除了Eq一個會比你寫的更有效)。不需要擴展!

然後,如果你想a是一個特定的類型,你只是這麼說!

-- Version1.hs 
myValue1 :: Power CountrySet1 
myValue1 = ... 


-- Version2.hs 
myValue2 :: Power CountrySet2 
myValue2 = ... 

這些都是完全兼容的,兩個實現可以並存在一起。

+3

另見[Luke Palmer的這篇文章](http://lukepalmer.wordpress.com/2010/11/23/encapsulation-considered-harmful/)。 – 2012-08-06 23:15:54

+1

@Ptharien的火焰哇,這真的寫得很好。我正在爲教學添加書籤。 – 2012-08-06 23:37:24

+1

如何調整數據省{power :: Power,...'相應地? (第19行,對不起,我不知道如何顯示行號) – 2012-08-07 00:29:06