For reference, here are the terms ...
data Term a =
Var a
| Lambda a (Term a)
| Apply (Term a) (Term a)
(I note that the representation of variables is abstracted out, which is often a good plan.)
... and here is the proposed function.
fmap' :: (Term a β Term a) β Term a β Term a
fmap' f (Var v) = f (Var v)
fmap' f (Lambda v t) = Lambda v (fmap' f t)
fmap' f (Apply t1 t2) = Apply (fmap' f t1) (fmap' f t2)
, , f (Var v), .
subst :: (a β Term a) β Term a β Term a
subst f (Var v) = f v
subst f (Lambda v t) = Lambda v (subst f t)
subst f (Apply t1 t2) = Apply (subst f t1) (subst f t2)
, , Term a Monad (>>=). , Functor Monad . Bird and Paterson , .
, , , - , uniplate, . , , , - & rsquo; .
tmFold :: (x -> y) -> (x -> y -> y) -> (y -> y -> y) -> Term x -> y
tmFold v l a (Var x) = v x
tmFold v l a (Lambda x t) = l x (tmFold v l a t)
tmFold v l a (Apply t t') = a (tmFold v l a t) (tmFold v l a t')
v, l a Term - , y, Term x, , , . y m (Term x) m (, ), Term x. , y, y . .
( ) fold-operator. , , .
data Fix f = In (f (Fix f))
fixFold :: Functor f => (f y -> y) -> Fix f -> y
fixFold g (In xf) = g (fmap (fixFold g) xf)
data TermF a t
= VarF a
| LambdaF a t
| ApplyF t t
type Term a = Fix (TermF a)
Term a, TermF a t , t . Term, Fix. , In, .
var x = In (VarF x)
lambda x t = In (LambdaF x t)
apply t t' = In (Apply x t t')
. , fixFold - . a y ,
TermF a y -> y
( v, l a ) , , y. , , .