我正在学习哈斯克尔的代数DT。我想做的是创建一个新的ADT,这种"扩展"现有的ADT。我找不到如何表达我想要的东西,有人可以提出替代模式或解决方案。我希望它们是不同的类型,但复制和粘贴只是接缝,就像一个愚蠢的解决方案。下面的代码最好地描述了我正在寻找的内容。
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)
编辑:我认为需要澄清一下...我希望能够做到这一点(以 ghci 为单位)
let a = Abkhazia :: Country
而不是
let a = Power Abkhazia :: Country
您需要将它们表示为一棵树:
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)
编辑:您对问题的扩展使这更简单一些:国家/地区和权力类型都与"国家/地区"共享一些共同的行为。这建议你使用 Haskell 的开放、可扩展的类型类特性来为数据类型提供常见行为。例如
data Power = Abkhazia | Transistria
data Countries = Neutral | Water
然后,一个类型类,用于权力和国家共享的事物:
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
然后,您可以在大国或国家上干净利落地使用landarea
。将来可以通过添加更多实例将其扩展到新类型。
{-# 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
编辑:另一种选择是type Power = forall a. CountryLike a
(优点:使Power
成为Country
的子类型。缺点:这将使例如 Power -> Int
更高等级的类型,这往往很烦人(类型推断等))