Haskell重构建议

Ra *_*ead 2 refactoring haskell functional-programming

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

如果我使用OOP,这对我来说很容易实现,但我不能认为"功能性".

谢谢你的时间.

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
Run Code Online (Sandbox Code Playgroud)

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" 
Run Code Online (Sandbox Code Playgroud)

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" 
Run Code Online (Sandbox Code Playgroud)

Gab*_*lez 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 ...
Run Code Online (Sandbox Code Playgroud)

......或者你可以做大多数人做和使用的事情deriving:

data Power a = Power a | Neutral | Water deriving (Eq, Show)
Run Code Online (Sandbox Code Playgroud)

这会生成与您编写的完全相同的实例(除了Eq一个将比您编写的更有效).无需扩展!

那么如果你想a成为一个特定的类型,你就这么说!

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


-- Version2.hs
myValue2 :: Power CountrySet2
myValue2 = ...
Run Code Online (Sandbox Code Playgroud)

然后这些完全兼容,并且两种实现可以彼此共存.

  • 另见[Luke Palmer的这篇文章](http://lukepalmer.wordpress.com/2010/11/23/encapsulation-considered-harmful/). (3认同)