I am looking for some refactoring / Best practice advice on the following code. I would like to try to avoid the extensions while maintaining separate modules for different “versions” that are mutually exclusive. My current solution is to use a class and use existential quantification to create a common type for each of the CountrySets.
This is an easy thing for me to accomplish if I was using OOP, but I can’t seam to think “functional” yet.
Thanks for your time.
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"
You don’t have to put class constraints in the data types. You can instead parametrize your data type on the
avariable so that you can place the constraints on the type-class instances themselves, like so:… or you could do what most people do and use
deriving:This generates the exact same instances you wrote (except the
Eqone will be much more efficient than what you wrote). No extensions required!Then if you want
ato be a specific type, you just say so!These are then completely compatible and both implementations can coexist alongside each other.