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 umModule
embrulhaModuleT
, 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?