data Expr f = In (f (Expr f)) data Val e = ValC Int type IntExpr = Expr Val -- λ> In (ValC 3) -- In (ValC 3) :: Expr Val data Add e = AddC e e type AddExpr = Expr Add -- In (_: Add (Expr Add)) -- In $ AddC (_: Expr Add) (_: Expr Add) -- λ> In (AddC (In (ValC 2)) (In (ValC 3))) data (f :+: g) e = Inl (f e) | Inr (g e) type IntAddExpr = Expr (Val :+: Add) -- In (Inr _) -- In (Inr AddC (In (Inl (ValC 2))) -- (In (Inl (ValC 3)))) a = In (Inr (AddC (In (Inl (ValC 2))) (In (Inl (ValC 3))))) b = In $ Inr $ AddC (In (Inl (ValC 2))) (In (Inl (ValC 3))) c = In $ Inr $ AddC (In $ Inl $ ValC 2) (In $ Inl $ ValC 3)