module Data.Comp.Multi.Sum
(
(:<<:)(..),
(:++:)(..),
hproj2,
hproj3,
hproject,
hproject2,
hproject3,
deepHProject,
deepHProject2,
deepHProject3,
hinj2,
hinj3,
hinject,
hinject2,
hinject3,
deepHInject,
deepHInject2,
deepHInject3,
deepHInjectE,
deepHInjectE2,
deepHInjectE3,
hinjectHConst,
hinjectHConst2,
hinjectHConst3,
hprojectHConst,
hinjectHCxt,
liftHCxt,
substHHoles,
) where
import Data.Comp.Multi.Functor
import Data.Comp.Multi.Traversable
import Data.Comp.Multi.ExpFunctor
import Data.Comp.Multi.Ops
import Data.Comp.Multi.Term
import Data.Comp.Multi.Algebra
import Control.Monad (liftM)
hproj2 :: forall f g1 g2 a i. (g1 :<<: f, g2 :<<: f) =>
f a i -> Maybe (((g1 :++: g2) a) i)
hproj2 x = case hproj x of
Just (y :: g1 a i) -> Just $ hinj y
_ -> liftM hinj (hproj x :: Maybe (g2 a i))
hproj3 :: forall f g1 g2 g3 a i. (g1 :<<: f, g2 :<<: f, g3 :<<: f) =>
f a i -> Maybe (((g1 :++: g2 :++: g3) a) i)
hproj3 x = case hproj x of
Just (y :: g1 a i) -> Just $ hinj y
_ -> case hproj x of
Just (y :: g2 a i) -> Just $ hinj y
_ -> liftM hinj (hproj x :: Maybe (g3 a i))
hproject :: (g :<<: f) => NatM Maybe (HCxt h f a) (g (HCxt h f a))
hproject (HHole _) = Nothing
hproject (HTerm t) = hproj t
hproject2 :: (g1 :<<: f, g2 :<<: f) =>
NatM Maybe (HCxt h f a) ((g1 :++: g2) (HCxt h f a))
hproject2 (HHole _) = Nothing
hproject2 (HTerm t) = hproj2 t
hproject3 :: (g1 :<<: f, g2 :<<: f, g3 :<<: f) =>
NatM Maybe (HCxt h f a) ((g1 :++: g2 :++: g3) (HCxt h f a))
hproject3 (HHole _) = Nothing
hproject3 (HTerm t) = hproj3 t
deepHProject :: (HTraversable f, HFunctor g, g :<<: f)
=> NatM Maybe (HCxt h f a) (HCxt h g a)
deepHProject = appHSigFunM hproj
deepHProject2 :: (HTraversable f, HFunctor g1, HFunctor g2,
g1 :<<: f, g2 :<<: f)
=> NatM Maybe (HCxt h f a) (HCxt h (g1 :++: g2) a)
deepHProject2 = appHSigFunM hproj2
deepHProject3 :: (HTraversable f, HFunctor g1, HFunctor g2, HFunctor g3,
g1 :<<: f, g2 :<<: f, g3 :<<: f)
=> NatM Maybe (HCxt h f a) (HCxt h (g1 :++: g2 :++: g3) a)
deepHProject3 = appHSigFunM hproj3
hinj2 :: (f1 :<<: g, f2 :<<: g) => (f1 :++: f2) a :-> g a
hinj2 (HInl x) = hinj x
hinj2 (HInr y) = hinj y
hinj3 :: (f1 :<<: g, f2 :<<: g, f3 :<<: g) => (f1 :++: f2 :++: f3) a :-> g a
hinj3 (HInl x) = hinj x
hinj3 (HInr y) = hinj2 y
hinject :: (g :<<: f) => g (HCxt h f a) :-> HCxt h f a
hinject = HTerm . hinj
hinject2 :: (f1 :<<: g, f2 :<<: g) => (f1 :++: f2) (HCxt h g a) :-> HCxt h g a
hinject2 = HTerm . hinj2
hinject3 :: (f1 :<<: g, f2 :<<: g, f3 :<<: g)
=> (f1 :++: f2 :++: f3) (HCxt h g a) :-> HCxt h g a
hinject3 = HTerm . hinj3
deepHInject :: (HFunctor g, HFunctor f, g :<<: f) => HCxt h g a :-> HCxt h f a
deepHInject = appHSigFun hinj
deepHInject2 :: (HFunctor f1, HFunctor f2, HFunctor g, f1 :<<: g, f2 :<<: g)
=> HCxt h (f1 :++: f2) a :-> HCxt h g a
deepHInject2 = appHSigFun hinj2
deepHInject3 :: (HFunctor f1, HFunctor f2, HFunctor f3, HFunctor g,
f1 :<<: g, f2 :<<: g, f3 :<<: g)
=> HCxt h (f1 :++: f2 :++: f3) a :-> HCxt h g a
deepHInject3 = appHSigFun hinj3
deepHInjectE :: (HExpFunctor g, g :<<: f) => HTerm g :-> HTerm f
deepHInjectE = hcataE hinject
deepHInjectE2 :: (HExpFunctor g1, HExpFunctor g2, g1 :<<: f, g2 :<<: f) =>
HTerm (g1 :++: g2) :-> HTerm f
deepHInjectE2 = hcataE hinject2
deepHInjectE3 :: (HExpFunctor g1, HExpFunctor g2, HExpFunctor g3,
g1 :<<: f, g2 :<<: f, g3 :<<: f) =>
HTerm (g1 :++: g2 :++: g3) :-> HTerm f
deepHInjectE3 = hcataE hinject3
hinjectHCxt :: (HFunctor g, g :<<: f) => HCxt h' g (HCxt h f a) :-> HCxt h f a
hinjectHCxt = hcata' hinject
liftHCxt :: (HFunctor f, g :<<: f) => g a :-> HContext f a
liftHCxt g = simpHCxt $ hinj g
substHHoles :: (HFunctor f, HFunctor g, f :<<: g)
=> (v :-> HCxt h g a) -> HCxt h' f v :-> HCxt h g a
substHHoles f c = hinjectHCxt $ hfmap f c
hinjectHConst :: (HFunctor g, g :<<: f) => HConst g :-> HCxt h f a
hinjectHConst = hinject . hfmap (const undefined)
hinjectHConst2 :: (HFunctor f1, HFunctor f2, HFunctor g, f1 :<<: g, f2 :<<: g)
=> HConst (f1 :++: f2) :-> HCxt h g a
hinjectHConst2 = hinject2 . hfmap (const undefined)
hinjectHConst3 :: (HFunctor f1, HFunctor f2, HFunctor f3, HFunctor g,
f1 :<<: g, f2 :<<: g, f3 :<<: g)
=> HConst (f1 :++: f2 :++: f3) :-> HCxt h g a
hinjectHConst3 = hinject3 . hfmap (const undefined)
hprojectHConst :: (HFunctor g, g :<<: f) => NatM Maybe (HCxt h f a) (HConst g)
hprojectHConst = fmap (hfmap (const (K ()))) . hproject