Avoiding boilerplate when dealing with many unrelated types

旧时模样 提交于 2019-12-05 19:48:15

问题


I'm writing code that deals with values from Language.Exts.Annotated.Syntax, where a variety of types are defined that mirror the structure of a Haskell module:

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

I'd like to be able to write functions that walk these data structures and perform various transformations on them. Because there's no one common data type, I can't write one function that does everything.

So far I've written a Tree type that wraps each of these types so that my transformation function can do Tree l -> Tree l:

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

However I'm now finding myself writing a lot of code that takes a Module, wraps it ModuleT, calls a function, then unwraps the result back to Module again. I have:

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

Two questions:

  1. Given that I can't change the types in Language.Exts.Annotated.Syntax, am I going about this the wrong way?
  2. If not, can I cut down on all this boilerplate somehow?

回答1:


All of those types seem to be instances of Typeable and Data. You can define your type Tree to be an instance of Typeable and Data as well, and then use one of the available generics libraries (SYB, uniplate, ...) to traverse the Tree with ease.

My personal favorite is uniplate. For example, collecting all GuardedAlt from Tree would be as easy as:

import Data.Uniplate.PlateData

...

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

You could take a look at my package graphtype where I did similar things.



来源:https://stackoverflow.com/questions/1855371/avoiding-boilerplate-when-dealing-with-many-unrelated-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!