We have an AST definition:
data Term a
= Lam String a
| App a a
| Var String
deriving(Read,Show,Eq,Functor,Foldable,Traversable)
And an F-Algebra for the type inference:
type Wrapped m a = Enviroment -> m a
type Result m = Wrapped (Type,Substitution)
w ::
(MonadState Int, MonadError TypeError)
=> Term (Result m)
-> Result m
w term env = ...
We can get the result of running the inference using cata:
infer ::
(MonadState Int, MonadError TypeError)
=> Fix Term
-> Result m
infer ast = cata hm ast
But now I want the result to be the original AST annotated with type information for each expression, So now infer' :: Fix Term -> Wrapped (Labeled Term Type).
- What data structure should I use to annotate the tree (
Cofree,Product,Fixwith a customLabel)? - How can I implement this using recursion schemes, without modifying the original
wfunction?
This answer does modify the function
w, but it still aims to keep the "workhorse" functions disentangled from the recursion-schemes machinery.Let's keep the
Termtype as is, and assume we have a typeEfor the environment that is calculated downwards, and a typeRfor the final annotation that is calculated upwards from the leaves.Let's also assume that we have these two functions:
I'm using
IOas the monad for simplicity.(Notice that I'm assuming that "calculating the environment" can't have effects. I this isn't the case then this solution won't do.)
We work in two phases. First we construct a tree in which the nodes have been annotated with their environments. We use an anamorphism, instead of the "trick" of returning a function from a catamorphism.
(Keep in mind that
type instance Base (Cofree f a) = CofreeF f a. That's where theCOFREEF.:<comes from. It's basically a pair of a pure value and another value wrapped in the functor.)And in the next phase we effectfully consume the annotated tree from the leaves to produce the final result —a tree with
Rannotations:I did in two phases because I was having trouble combining the "returning a function" trick with returning an annotated tree.
An anamorphism followed by a catamorphism is known as hylomorphism. We could define the composed function using
hylo, like this:You can put together
calcEnvandcalcResultin the form of the original algebra like this: