Extend a complex data type with a common way in Haskell

I use the Language.C library Abstract Syntax Tree (AST) to modify C programs using common SYB library transformations . This AST has different types of nodes (data types), each of which is a construction C, i.e. Expressions, statements, definitions, etc. I now need to somehow increase the information that the data contains, i.e. Annotate them. I assumed (maybe I'm wrong) that I cannot change or override the original data type, so I would like to have something like this:

annotateAST anns =
   everywhere (mkT (annotateAST_ anns))

annotateAST_ astnode anns 
  | isStmt astnode = AnnStmt astnode (getAnn astnode anns)
  | otherwise = astnode

This way I will have a new ash with annotated statements instead of the original one. Of course, the GHC is about to complain because it everywheremust return the same type that it receives, and that’s not what happens here.

In conclusion, I need to outline the AST in general terms without changing the original data types and in such a way that it is easy to return to the original data structure. I thought about various solutions to this problem, but I am not convinced of any of them, so I decided to share it here.

PS I was told that the SYB library is not very efficient. Given that Language.C language AST only outputs data, do I have a better alternative to general AST traversal and modification?

+4
1

, , , , .

, NodeInfo, ( ). .

type CTranslUnit = CTranslationUnit NodeInfo

type MyTransUnit = CTranslationUnit MyNodeInfo
data MyNodeInfo = MNI NodeInfo AdditionalStuffHere

, .

Functor, , Annotated (, ) AST node.

.


. , , , , , . :

-- AST library for a simple lambda-calculus
data AST n
    = Fun n String (AST n)
    | Var n String
    | App n (AST n) (AST n)

-- user code
data Annotation
    = AnnVar ... | AnnFun ... | AnnApp ...
type AnnotatedAST = AST Annotation

, AnnFun.

, GADT, :

-- AST library for a simple lambda-calculus
data Tag = TagFun | TagVar | TagApp
data AST (n :: Tag -> *)
    = Fun (n 'TagFun) String (AST n)
    | Var (n 'TagVar) String
    | App (n 'TagApp) (AST n) (AST n)

-- user code
data Annotation (n :: Tag) where
   AnnFun :: String -> Annotation 'TagFun
   AnnVar :: Int    -> Annotation 'TagVar
   AnnApp :: Bool   -> Annotation 'TagApp
type AnnotatedAST = AST Annotation

node. AST Functor, Functor -like , .

- , , , .

+3

Source: https://habr.com/ru/post/1617049/


All Articles