I am learning about Algebraic DTs in haskell. What I would like to do is create a new ADT that kind of "extends" an existing one. I cannot find how to express what I would like, can someone sugest an alternative pattern or sugest a solution. I want them to be distinct types, but copying and pasting just seams like a silly solution. The code below best describes what I am seeking.
data Power =
Abkhazia |
-- A whole bunch of World powers and semi-powers
Transnistria
deriving (Eq, Show)
data Country =
--Everything in Power |
Netural |
Water
deriving (Eq, Show)
Edit: I think It need a little clarification... I want to be able to do this (in ghci)
let a = Abkhazia :: Country
and not
let a = Power Abkhazia :: Country
You need to represent them as a tree:
data Power
= Abkhazia
| Transnistria
deriving (Eq, Show)
data Country
= Powers Power -- holds values of type `Power`
| Netural -- extended with other values.
| Water
deriving (Eq, Show)
Edit: your extension to the question makes this a bit simpler: both the Country and Power types share some common behavior as "countries". This suggests you use the open, extensible type class feature of Haskell to given common behaviors to the data type. E.g.
data Power = Abkhazia | Transistria
data Countries = Neutral | Water
then, a type class for things both Power and Countries share:
class Countrylike a where
landarea :: a -> Int -- and other things country-like entities share
instance Countrylike Power where
landarea Abkhazia = 10
landarea Transistria = 20
instance Countrylike Countries where
landarea Neutral = 50
landarea Water = 0
then you can use landarea
cleanly on either powers or countries. And you can extend it to new types in the future by adding more instances.
{-# LANGUAGE GADTs, StandaloneDeriving #-}
data POWER
data COUNTRY
data CountryLike a where
Abkhazia :: CountryLike a
Transnistria :: CountryLike a
Netural :: CountryLike COUNTRY
Water :: CountryLike COUNTRY
deriving instance Show (CountryLike a)
deriving instance Eq (CountryLike a)
type Power = CountryLike POWER
type Country = CountryLike COUNTRY
foo :: Power
foo = Abkhazia
bar :: Country
bar = Abkhazia
baz :: Country
baz = Netural
Edit: An alternative would be type Power = forall a. CountryLike a
(Advantage: Makes Power
a subtype of Country
. Disadvantage: This would make e.g. Power -> Int
a higher-rank type, which tend to be annoying (type inference etc.))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With