2012-06-17 13 views
5

Sto imparando a conoscere i DT algebrici in haskell. Quello che mi piacerebbe fare è creare un nuovo ADT che "estenda" uno esistente. Non riesco a trovare come esprimere ciò che vorrei, qualcuno può suggerire un modello alternativo o suggerire una soluzione. Voglio che siano tipi distinti, ma copiare e incollare solo le giunture come una soluzione sciocca. Il codice seguente descrive meglio quello che sto cercando.Tipi di dati algebrici di Haskell: "pseudo-estensione"

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: Credo che hanno bisogno di un piccolo chiarimento ... Voglio essere in grado di fare questo (in ghci)

let a = Abkhazia :: Country 

e non

let a = Power Abkhazia :: Country 
+1

I motivi per cui voglio farlo solitamente provengono da una scuola di pensiero OO-y ;-), ma puoi sempre aggiungere un costruttore all'interno di Country per PowerCountry che detiene un potere. –

+0

Hmm posso chiedere come Abkhazia e Transnistria entrano in un pezzo di codice Haskell? Come sei collegato a quei due posti? Stai lavorando ad una sorta di gioco? Da quale paese vieni? –

+0

Abkhazia e Transnistria sono i primi e gli ultimi nell'elenco di "Altri stati" su http://en.wikipedia.org/wiki/List_of_sovereign_states Sto solo imparando Haskell e ho trovato qualcosa da praticare. Immagino che potrebbe essere un gioco, ma non ho ancora intenzione. –

risposta

8

È necessario rappresentarli come un albero:

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) 

Modifica: la tua estensione alla domanda lo rende un po 'più semplice: sia il Paese che i tipi di potere condividono alcuni comportamenti comuni come "paesi". Ciò suggerisce di utilizzare la funzione della classe di tipo di Haskell estendibile per attribuire comportamenti comuni al tipo di dati. Per esempio.

data Power = Abkhazia | Transistria 

    data Countries = Neutral | Water 

poi, una classe tipo per le cose potenza e paesi condividono:

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 

quindi è possibile utilizzare landarea modo pulito su entrambi i poteri o paesi. Ed è possibile estenderlo a nuovi tipi in futuro aggiungendo più istanze.

+0

Questo è quasi quello che voglio, ma guarda il chiarimento. Grazie! –

+1

@Risultato non puoi farlo in Haskell, e Don lo saprebbe, ... (Tuttavia, puoi usare classi di tipo multiparametro per simulare il sottotipo, che potrebbe essere quello che intendi. In ogni caso, la risposta di Don è probabilmente la migliore otterrai e cosa dovresti usare). –

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 

Edit: Un'alternativa sarebbe type Power = forall a. CountryLike a (Vantaggio: Rende Power un sottotipo di Country Svantaggio:. Questo renderebbe ad esempio Power -> Int un tipo più alto rango, che tendono ad essere fastidioso (inferenza di tipo etc.))

Problemi correlati