Haskell的代数数据类型:“伪扩展”

5
我正在学习Haskell中的代数数据类型。我想要做的是创建一个新的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

1
想要这样做的原因通常来自于面向对象的思想;-),但你可以在Country中添加一个构造函数,用于持有Power的PowerCountry。 - Kristopher Micinski
嗯,我可以问一下阿布哈兹和德涅斯特河沿岸地区如何出现在Haskell代码中吗?你与这两个地方有什么关系?你正在开发某种游戏吗?你来自哪个国家? - Cetin Sert
阿布哈兹和德涅斯特河沿岸地区是http://en.wikipedia.org/wiki/List_of_sovereign_states上“其他国家”列表中的第一个和最后一个。我正在学习Haskell,并想出了一些练习。我猜它可能是一个游戏,但我还没有打算。 - Ra is dead
2个回答

8

你需要将它们表示为一棵树:

  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

然后,一个类型类适用于Power和Countries这两个事物:

  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

然后你可以在powers或countries上干净地使用landarea。通过添加更多实例,您还可以将其扩展到未来的新类型。


这几乎是我想要的,但请看一下澄清。谢谢! - Ra is dead
1
@Raisdead,你在Haskell中是做不到的,Don会知道的...(但是,你可以使用多参数类型类来模拟子类型,这可能是你的意思。无论如何,Don的答案可能是你能得到的最好的答案,也是你应该使用的。) - Kristopher Micinski

2
{-# 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成为更高级别的类型,这往往很麻烦(类型推断等)。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接