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
,Fix
with a customLabel
)? - How can I implement this using recursion schemes, without modifying the original
w
function?
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
Term
type as is, and assume we have a typeE
for the environment that is calculated downwards, and a typeR
for the final annotation that is calculated upwards from the leaves.Let's also assume that we have these two functions:
I'm using
IO
as 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
R
annotations: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
calcEnv
andcalcResult
in the form of the original algebra like this: