\begin{code} module Generate (mono, apply) where import Syntax (Type(..), Func(..), Term(..)) mono :: Type -> Func v -> Func v -> Func v mono Alpha pre post = post mono Bool pre post = Id mono Int pre post = Id mono (List t) pre post = Map "map" (mono t pre post) mono (Maybe t) pre post = Map "fmap" (mono t pre post) mono (s `To` t) pre post = Lambda (\h -> mono t pre post `Comp` Embed h `Comp` mono s post pre) apply :: Func (Term v) -> Term v -> Term v f `apply` t | isId f = t f `apply` t | Just f' <- isSimple f = f' `Apply` t Map name f `apply` t = Const name `Apply` Lambda' (\v -> f `apply` (Var v)) `Apply` t Lambda f `apply` t = Lambda' (\v -> f t `apply` (Var v)) (f `Comp` g) `apply` t = f `apply` (g `apply` t) Embed f `apply` t = f `Apply` t isId :: Func v -> Bool isId Id = True isId (Map _ f) = isId f isId (f `Comp` g) = isId f && isId g isId _ = False isSimple :: Func (Term v) -> Maybe (Term v) isSimple (Embed f@(Var _)) = Just f isSimple (Map name f) | Just f' <- isSimple f = Just (Const name `Apply` f') isSimple _ = Nothing \end{code}