2014-11-01 16 views
14

Sto appena iniziando ad imparare Haskell. Ho visto molti esempi introduttivi che spiegano le basi dei tipi, ma spesso hanno un'istruzione deriving sotto il tipo. Ecco un esempio da Chapter 3 of RealWorldHaskell:Cosa succede sotto il cofano con `derivando` in Haskell?

data Cartesian2D = Cartesian2D Double Double 
        deriving (Eq, Show) 

data Polar2D = Polar2D Double Double 
       deriving (Eq, Show) 

Essi spiegano che deriva un po 'in Chapter 6, che ti aiuta a sapere come vengono utilizzati.

Così lontano da quello che ho capito, deriving (Show) è necessario dire a Haskell come trasformare il tuo testo in una stringa. Questo ha senso a livello pratico. Io vengo dalla terra JavaScript, quindi per me si potrebbe facilmente immaginare questo sarebbe stato implementato come:

Polar2D.prototype.toString = function(){ 
    return '[Polar2D]'; 
}; 

In Haskell, danno l'esempio di come implementare il proprio Show per il tipo Color, invece di utilizzare deriving.

data Color = Red | Green | Blue 
instance Show Color where 
    Red = "red" 
    Green = "green" 
    Blue = "blue" 

Questo significa che quando il vostro nelle ghci repl, si può fare:

> show Red 
"red" 

Ma questo non spiega che cosa deriving sta effettivamente facendo, è ancora magica per me.

La mia domanda è, cosa sta succedendo sotto il cofano con deriving? Inoltre, c'è un posto su GitHub nella fonte Haskell dove puoi vedere l'implementazione? Potrebbe anche essere utile.

risposta

16

GHC sta semplicemente scrivendo la stessa istanza che hai scritto a mano, se passi il -ddump-deriv al compilatore puoi vedere il codice che genera. Per esempio:

Prelude> data Color = Red | Green | Blue deriving (Show) 

==================== Derived instances ==================== 
Derived instances: 
    instance Show Color where 
    showsPrec _ Red = showString "Red" 
    showsPrec _ Green = showString "Green" 
    showsPrec _ Blue = showString "Blue" 
    showList = showList__ (showsPrec 0) 


Generic representation: 

    Generated datatypes for meta-information: 

    Representation types: 

Non c'è davvero molto di magia sta succedendo qui, Show deve solo un'implementazione molto meccanico. All'interno esamina la forma interna dei costruttori di dati (il tipo è DataConRep nella sorgente di GHC) che ottiene dalla traduzione del frontend AST e poi osserva i nomi forniti nella sorgente di frontend e aggiunge una nuova istanza Show in termini di questi nomi e tutti i tipi annidati che implementano anche Show. Il nuovo typeclass generato automaticamente è registrato come una classe codificata a mano come se fosse stato scritto nel modulo corrente.

+0

questo è vero qui, ma alcune cose strane possono accadere (anche se non sono un esperto di GHC). come [1] con 'GeneralizedNewTypeDeriving', non genera istanze, ma riutilizza in sicurezza le istanze dei tipi interni. anche [2] con 'DeriveDataTypeable', non puoi scrivere un'istanza' Typeable' manuale. –

Problemi correlati