5

我正在学习 Haskell 中的代数 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
4

2 回答 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)

编辑:您对问题的扩展使这变得更简单: Country 和 Power 类型都具有一些作为“国家”的共同行为。这建议您使用 Haskell 的开放、可扩展类型类特性来为数据类型提供常见行为。例如

  data Power = Abkhazia | Transistria 

  data Countries = Neutral | Water

然后,Power 和 Country 共享的东西的类型类:

  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在大国或国家/地区干净利落地使用。您可以在未来通过添加更多实例将其扩展到新类型。

于 2012-06-17T18:07:46.403 回答
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更高级别的类型,这往往很烦人(类型推断等))

于 2012-06-17T22:55:40.680 回答