2012-08-06 47 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