{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Comp.Multi.Annotation
(
(:&:) (..),
DistAnn (..),
RemA (..),
liftA,
ann,
liftA',
stripA,
propAnn,
project'
) where
import Data.Comp.Multi.Algebra
import Data.Comp.Multi.HFunctor
import Data.Comp.Multi.Ops
import Data.Comp.Multi.Term
import qualified Data.Comp.Ops as O
liftA :: (RemA s s') => (s' a :-> t) -> s a :-> t
liftA f v = f (remA v)
ann :: (DistAnn f p g, HFunctor f) => p -> CxtFun f g
ann c = appSigFun (injectA c)
liftA' :: (DistAnn s' p s, HFunctor s')
=> (s' a :-> Cxt h s' a) -> s a :-> Cxt h s a
liftA' f v = let (v' O.:&: p) = projectA v
in ann p (f v')
stripA :: (RemA g f, HFunctor g) => CxtFun g f
stripA = appSigFun remA
propAnn :: (DistAnn f p f', DistAnn g p g', HFunctor g)
=> Hom f g -> Hom f' g'
propAnn alg f' = ann p (alg f)
where (f O.:&: p) = projectA f'
project' :: (RemA f f', s :<: f') => Cxt h f a i -> Maybe (s (Cxt h f a) i)
project' (Term x) = proj $ remA x
project' _ = Nothing