2

Using cata I can fold an AST to a result. With Cofree I can store additional annotations on the AST. How can I take an AST and return an annotated AST with the results at each step of the way?

alg :: Term Result -> Result
alg = undefined

run :: Fix Term -> Result
run ast = cata alg ast

run' :: Fix Term -> Cofree Term Result
run' = ???
user47376
  • 2,263
  • 3
  • 21
  • 26

2 Answers2

2

Does this modified algebra work?

alg' :: Term (Cofree Term Result) -> Cofree Term Result
alg' t = alg (fmap extract t) :< t  

run' :: Fix Term -> Cofree Term Result
run' ast = cata alg' ast

extract is from Control.Comonad. We are using it here with type Cofree Term Result -> Result. It simply returns the annotation at the root.

fmap extract :: Term (Cofree Term Result) -> Term Result lets us reuse our previous alg definition.

danidiaz
  • 26,936
  • 4
  • 45
  • 95
  • Thanks! But there is another problem: actually my `Result` is wrapped in a monad. So `run' :: Fix Term -> Cofree Term (m Result)`. What can I do to get `m (Cofree Term Result)` ? – user47376 Sep 09 '17 at 16:18
  • @user47376 Is your original algebra like `alg :: Term (m Result) -> m Result` ? – danidiaz Sep 09 '17 at 17:07
  • Yes. The full type is `hm :: (MonadError TypeError m,MonadState Count m) => Term (Alias m) -> Alias m`. Where `type Alias m = Enviroment -> m (Substitution,Type)`. So it's actually wrapped in all sorts of things. I'm only interested in `Type`. So the final result should be `Cofree Term Type` – user47376 Sep 09 '17 at 17:10
  • @user47376 In that case I'm not sure how to reutilize `alg` in the definition of `alg'`. But perhaps you could define `alg'` (the algebra that returns annotated trees) directly and work with it from the start? It's easy to "forget the tree" and just keep the root result, after all. – danidiaz Sep 09 '17 at 18:28
  • @user47376 I've just remember that there exists a recursion scheme called "histomorphism" which comes with the "Cofree annotating all previous results" baked-in. https://stackoverflow.com/questions/24884475/examples-of-histomorphisms-in-haskell http://hackage.haskell.org/package/recursion-schemes-5.0.2/docs/Data-Functor-Foldable.html#v:histo I'm still unsure about how to integrate it with returning functions / monadic effects. – danidiaz Sep 10 '17 at 14:37
0

If you just need a simple catamorphism, you could use a function like cataM. This allows you to fold monadic values such that the actions are properly ordered. Plus, you don't need to write any boilerplate to wrap your F-algebra.

Then

alg :: Term Result -> Cofree Term Result
alg = undefined

run' :: Fix Term -> Cofree Term Result
run' = cataM alg