2012-12-15 13 views
5

Diciamo che voglio definire un albero come questo:Alternativa per deprecato -XDatatypeContext?

{-# LANGUAGE DatatypeContexts #-} 
class Node a where 
    getContent :: (Num a) => a 

data (Node a) => Tree a = Leaf a 
         | Branch a (Tree a) (Tree a) 

-XDatatypeContexts è deprecato ora. È possibile fare qualcosa di simile senza di esso?

risposta

13

Sei sicuro che i contesti dei tipi di dati di tipo data facessero effettivamente quello che pensi che abbia fatto? Era deprecated because it was basically useless e ampiamente considerato una disfunzione, dal momento che tutto ciò che faceva era costringerti ad aggiungere vincoli extra senza fornire garanzie sui tipi oltre a quello che avresti avuto senza.

La sostituzione, come è, che in realtà fa qualcosa di utile, è GADT syntax. L'equivalente del vostro tipo sarebbe simile a questa:

data Tree a where 
    Leaf :: (Node a) => a -> Tree a 
    Branch :: (Node a) => a -> Tree a -> Tree a -> Tree a 

In questo caso, è necessario il vincolo Node durante la creazione di un valore Tree, ma quando pattern matching su un valore Tree anche di ottenere una garanzia automatica che un'istanza Node esiste, rendendo l'istanza disponibile senza nemmeno averne bisogno nel tipo di funzione che riceve Tree a come argomento.

+0

Grazie mille! Anche se penso tu intenda: Branch :: (Node a) => a -> Albero a -> Albero a – Jake

+0

@Jake: No - funziona come una firma del tipo di funzione, quindi l'ultimo 'Albero a' è il risultato tipo di dati. 'a -> Albero a -> Albero a 'avrebbe solo un sotto-albero. Confronta il tipo di costruttore 'Branch' che hai attualmente. –

+0

Oh, giusto, vedo. – Jake