2009-12-06 26 views
9

estoy escribiendo código que se ocupa de los valores de Language.Exts.Annotated.Syntax, donde se define una variedad de tipos que reflejan la estructura de un módulo de Haskell:repetitivo cuando se trata de muchos tipos no relacionados

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

me gustaría para poder escribir funciones que recorren estas estructuras de datos y realizar varias transformaciones en ellas. Como no hay un tipo de datos común, no puedo escribir una función que haga todo.

Hasta ahora he escrito un tipo Tree que envuelve cada uno de estos tipos para que mi función de transformación puede hacer Tree l -> Tree l:

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

Sin embargo ahora estoy encontrando a mí mismo escribiendo un montón de código que toma una Module, lo envuelve ModuleT, llama a una función y luego vuelve a desenvolver el resultado en Module. Tengo:

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 

Dos preguntas:

  1. Dado que no puedo cambiar los tipos de Language.Exts.Annotated.Syntax, lo voy de este por el camino equivocado?
  2. Si no, ¿puedo reducir todo este texto estándar de alguna manera?

Respuesta

6

Todos esos tipos parecen ser instancias de Tipo y Datos. Puede definir su tipo Tree para que también sea una instancia de Typeable y Data, y luego use una de las bibliotecas de genéricos disponibles (SYB, uniplate, ...) para recorrer el Árbol con facilidad.

Mi favorito personal es uniplate. Por ejemplo, la recopilación de toda GuardedAlt del árbol sería tan fácil como:

import Data.Uniplate.PlateData 

... 

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

Usted puede echar un vistazo a mi paquete graphtype donde hice cosas similares.

+1

uniplate parece justo lo que necesitaba, gracias. Ahora he eliminado mi repetición. –

+1

Con este enfoque ya no necesitas realmente tu tipo de árbol, ¿o sí? – Martijn

+0

Así es, yo no; Puedo configurar mis funciones de reescritura de árboles como una serie de aplicaciones rewriteBi, una para cada tipo que me interesa. –

Cuestiones relacionadas