2009-12-06 11 views
9

Sto scrivendo il codice che si occupa di valori da Language.Exts.Annotated.Syntax, in cui sono definite una varietà di tipi che rispecchiano la struttura di un modulo di Haskell:Evitare boilerplate quando si tratta di molti tipi non correlati

data Module l = ... 
data Decl l = ... 
data Exp t = ... 
-- etc 

mi piacerebbe essere in grado di scrivere funzioni che camminano su queste strutture dati ed eseguono varie trasformazioni su di esse. Poiché non esiste un tipo di dati comune, non posso scrivere una funzione che faccia tutto.

Finora ho scritto un tipo Tree che avvolge ciascuno di questi tipi in modo che la mia funzione di trasformazione può fare Tree l -> Tree l:

data Tree l = ModuleT (Module l) 
      | DeclT (Decl l) 
      | ExpT (Exp l) 
      -- etc copy & paste 

Comunque ora sto trovando a scrivere un sacco di codice che prende una Module, lo avvolge ModuleT, chiama una funzione, quindi scarta nuovamente il risultato su Module. Ho:

class AnnotatedTree ast where 
    tree :: ast l -> Tree l 
    untree :: Tree l -> ast l 

instance AnnotatedTree Module where 
    tree = ModuleT 
    untree (ModuleT x) = x 
    untree _ = error "expected ModuleT" 

-- etc ad nauseam 

Due domande:

  1. dato che non posso cambiare i tipi di Language.Exts.Annotated.Syntax, sto andare su questo nel modo sbagliato?
  2. In caso contrario, posso ridurre in qualche modo questa caldaia?

risposta

6

Tutti questi tipi sembrano essere tipi di dati e Typeable. È possibile definire il tipo Albero come un'istanza di Digitabile e Dati, quindi utilizzare una delle librerie generiche disponibili (SYB, uniplate, ...) per attraversare l'Albero con facilità.

Il mio preferito è uniplate. Ad esempio, la raccolta di tutti GuardedAlt da albero sarebbe stato facile come:

import Data.Uniplate.PlateData 

... 

allGuardedAlts :: Tree l -> [l] 
allGuardedAlts t = [ l | GuardedAlt l _ _ <- universeBi t] 

Si potrebbe dare un'occhiata al mio pacchetto graphtype dove ho fatto cose simili.

+1

uniplate sembra proprio quello di cui avevo bisogno, grazie. Ora ho scartato la mia caldaia. –

+1

Con questo approccio non hai più bisogno del tuo tipo di albero, vero? – Martijn

+0

Proprio così, io no; Posso configurare le mie funzioni di riscrittura degli alberi come una serie di applicazioni di riscritturaBi, una per ogni tipo a cui tengo. –

Problemi correlati