Evitando clichê ao lidar com muitos tipos não relacionados

Eu estou escrevendo código que lida com valores deLanguage.Exts.Annotated.Syntax, onde uma variedade de tipos são definidos que espelham a estrutura de um módulo Haskell:

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

Eu gostaria de poder escrever funções que percorrem essas estruturas de dados e executar várias transformações nelas. Como não há um tipo de dados comum, não posso escrever uma função que faça tudo.

Até agora eu escrevi umTree tipo que envolve cada um desses tipos para que minha função de transformação possa fazerTree l -> Tree l:

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

No entanto, estou agora a encontrar-me a escrever um monte de código que leva umModuleembrulhaModuleT, chama uma função e, em seguida, desembrulha o resultadoModule novamente. Eu tenho:

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

Duas questões:

Dado que eu não posso mudar os tipos em Language.Exts.Annotated.Syntax, eu estou indo sobre isso da maneira errada?Se não, posso reduzir todo esse clichê de alguma forma?

questionAnswers(1)

yourAnswerToTheQuestion