Haskell重构建议



我正在寻找一些关于以下代码的重构/最佳实践建议。我想尽量避免扩展,同时为相互排斥的不同"版本"维护单独的模块。我目前的解决方案是使用一个类并使用存在量化为每个CountrySets创建一个公共类型。

如果我使用OOP,这对我来说是一件很容易完成的事情,但我还不能把它想象成"功能性的"。

谢谢你抽出时间。

省份.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

版本1.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" 

版本2.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" 

您不必在数据类型中设置类约束。相反,您可以在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 = ...

然后它们是完全兼容的,并且这两种实现可以共存。

最新更新