2009-07-05 16 views
14

In Haskell, si può definire un tipo di dati in questo modo:classi di tipo a tipi di dati Haskell

data Point1 = Point1 { 
    x :: Integer 
    , y :: Integer 
} 

Can classi Un tipo uso per le variabili all'interno di un tipo di dati? Se é cosi, come? Mi rendo conto che è possibile farlo come un tipo di dati algebrico, con una definizione diversa per ogni tipo di punto, ma mi chiedo se c'è un modo per farlo in un modo più compatto e flessibile.

ad es. Qualcosa sulla falsariga di questo pseudocodice che usa la sintassi dichiarazione di funzione:

data Point2 = Point2 { 
    x :: (Num a, Ord a) => a 
    , y :: (Num a, Ord a) => a 
} 

L'obiettivo sarebbe quello di consentire di memorizzare Int, Integer, Float o doppie valori nei dati genere. Idealmente, mi piacerebbe restringerlo in modo che xey debbano essere dello stesso tipo.

risposta

18

È necessario decidere se si desidera una quantificazione esistenziale o universale per quel tipo. quantificazione universale, ala:

data (Num a, Ord a) => Point2 a = Point2 a a 

produce un obbligo di prova che esistono casi Num e Ord per il tipo 'a', ma in realtà non aiuta più di tanto, perché tutto ciò che fa è dare un obbligo quando si va usare la classe Point costruendo un valore di quel tipo o quando si va a modello lo si abbina.

In quasi tutti i casi, si sta meglio definire

data Point2 a = Point2 a a deriving (Eq,Ord,Show,Read) 

e rendendo ciascuna delle istanze contingenti sulle informazioni supplementari che si desidera.

instance Num a => Num (Point2 a) where 
    ... 

instance (Num a, Ord a) => SomeClass (Point2 a) where 
    ... 

Ciò consente di passare intorno e costruire un minor numero di dizionari superflui e aumenta il numero di scenari in cui il tipo di dati Point2 può essere utilizzato. D'altra parte la quantificazione esistenziale può farti dire che non ti importa di quale sia il tipo (più vicino a ciò che hai effettivamente richiesto, tipo saggio) a spese che non puoi usare nulla su di esso eccetto per le operazioni fornite dai vincoli specificati - un adattamento piuttosto scadente qui.

+2

Woohoo, questo è esattamente il punto che stavo ottenendo nel mio commento alla risposta di newacct ma era troppo pigro per scrivere :) – ephemient

+1

Questo è molto istruttivo. Ho finito per usare il commento di ephemient sopra nel mio codice. E la tua spiegazione mi ha aiutato a capire molto. (RWH non ha ancora coperto "istanza" ma è evidente ciò che fa dal contesto.) Grazie mille. – Gregyski

7

qualcosa di simile?

data (Num a, Ord a) => Point2 a = Point2 { 
    x :: a 
    , y :: a 
} 
+8

Più comunemente, si esce dal contesto nella dichiarazione dei dati e si utilizza "(Num a, Ord a) => Punto 2 a" nei luoghi in cui il tipo viene effettivamente utilizzato, ma anche questo funziona. – ephemient

+0

Grazie. Funziona perfettamente e ha anche senso ora che lo vedo. – Gregyski

+3

Questo non è il codice haskel legale per ghc 7.4.1 – mentatkgs

Problemi correlati