1

After parsing source code with megaparsec, I have an abstract syntax tree. In a second stage, I compute aggregates on each subtree, e.g. the list of variables it contains, by aggregating leaf values, and I want to store them somewhere, so I don't have to recompute them later. How should I do that ?

I have considered these options.

  • Add an aggregates value to each node. I would need to modify each node data type.
  • Wrap each node data type in a generic aggregate data type.
  • Use generics node data type, with aggregates, but I'm afraid compilation error messages won't be as clear.
  • Build a "shadow tree", with the same topology as the AST, but containing the aggregates.

What should I chose ?

Pierre Carbonnelle
  • 2,305
  • 19
  • 25
  • You also could simply build a function that computes the aggregate value for a subtree and memoize this function. This would be less intrusive to the existing code and also avoids recomputation. – mschmidt Oct 09 '17 at 05:55
  • Two more alternatives: 1) modify your AST to use `Fix` https://hackage.haskell.org/package/recursion-schemes-5.0.2/docs/Data-Functor-Foldable.html#t:Fix and then change the annotation function to use `Cofree`. https://stackoverflow.com/questions/38462563/how-to-work-with-ast-with-cofree-annotation 2) the Trees that Grow approach https://www.microsoft.com/en-us/research/wp-content/uploads/2016/11/trees-that-grow.pdf which adds fields to your AST that can change with each phase. – danidiaz Oct 09 '17 at 06:01
  • @danidiaz I’ve never understood why people seem to want to use `Cofree` for annotating a tree when `Product` does a much better job... – Benjamin Hodgson Oct 09 '17 at 09:32
  • @mschmidt : how do you look-up the memoization table, when nodes do not have an ID ? Eq would be costly, I would think. – Pierre Carbonnelle Oct 09 '17 at 14:23
  • @user474491 : you are right. I didn't think about the lookup. – mschmidt Oct 09 '17 at 16:37
  • @Benjamin Hodgson Do you mean using `Fix` over a `Product` of the functor and another functor? – danidiaz Oct 09 '17 at 18:58
  • @danidiaz Yes, exactly. `data (f :@ a) x = f x :@ a deriving Functor`; `type Annotated f a = Fix (f :@ a)`. No need for `Cofree` :) – Benjamin Hodgson Oct 09 '17 at 19:01

1 Answers1

1

The Trees that Grow approach (suggested by @danidiaz) looks like what I'm looking for.

Pierre Carbonnelle
  • 2,305
  • 19
  • 25