5 Stimmen

Die algebraischen Datentypen von Haskell: "pseudo-extend"

Ich lerne gerade über algebraische DTs in Haskell. Was ich tun möchte, ist eine neue ADT zu erstellen, die eine Art von "erweitert" eine bestehende. Ich kann nicht finden, wie man ausdrücken, was ich möchte, kann jemand ein alternatives Muster oder eine Lösung vorschlagen. Ich möchte, dass sie unterschiedliche Typen sind, aber Kopieren und Einfügen scheint nur wie eine dumme Lösung. Der Code unten beschreibt am besten, was ich suche.

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: Ich glaube, es bedarf einer kleinen Klarstellung... Ich möchte in der Lage sein, dies zu tun (in ghci)

let a = Abkhazia :: Country

und nicht

let a = Power Abkhazia :: Country

8voto

Don Stewart Punkte 136046

Sie müssen sie als einen Baum darstellen:

  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)

Bearbeiten: Ihre Erweiterung der Frage macht die Sache etwas einfacher: Die Typen "Land" und "Macht" haben ein gemeinsames Verhalten als "Länder". Dies legt nahe, dass Sie die offene, erweiterbare Typklasse Funktion von Haskell, um dem Datentyp allgemeine Verhaltensweisen zu geben. z.B.

  data Power = Abkhazia | Transistria 

  data Countries = Neutral | Water

dann eine Typklasse für Dinge, die sowohl Power als auch Countries gemeinsam haben:

  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

dann können Sie landarea entweder auf Mächte oder Länder. Und Sie können es in Zukunft auf neue Typen erweitern, indem Sie weitere Instanzen hinzufügen.

2voto

FunctorSalad Punkte 2262
{-# 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: Eine Alternative wäre type Power = forall a. CountryLike a (Vorteil: Ermöglicht Power ein Subtyp von Country . Nachteil: Dies würde z.B. dazu führen. Power -> Int einen Typ höheren Ranges, die eher lästig sind (Typinferenz usw.))

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X