--------------------------------------------------------------------------------
--                                                                            --
-- lifting only and sum from types to constructors                            --
--                                                                            --
--------------------------------------------------------------------------------

-- lifting only from types to constructors 

type O only f x = only (f x) in 
 parserO :: (Parser m (f x), Only only) => m (O only f x) , 
 mapO :: (Functor f, Only only) => (x -> y) -> O only f x -> O only f y ,
 phiO :: (Algebra f a, Only only) => O only f a -> a 

parserO = map only parser
mapO f = only . map f . ylno 
phiO = phi . ylno 

-- three important instances

instance (Parser m (f x), Only only) => Parser m (O only f x) where
  parser = parserO

instance (Functor f, Only only) => Functor (O only f) where
  map = mapO 
   
instance (Algebra f a, Only only) => Algebra (O only f) a where
  phi = phiO  
   
-- lifting sum from types to constructors

type S sum f g x = sum (f x) (g x) in

 parserS :: (Parser m (f x), Parser m (g x), Sum sum) 
          => m (S sum f g x) ,
 mapS :: (Functor f, Functor g, Sum sum) 
        => (x -> y) -> S sum f g x -> S sum f g y ,
 phiS :: (Algebra f a, Algebra g a, Sum sum) 
        => S sum f g a -> a  

parserS = map inl parser ++ map inr parser 
mapS g = inl . map g <+> inr . map g
phiS = phi <+> phi
      
-- three important instances

instance (Parser m (f x), Parser m (g x), Sum sum) => Parser m (S sum f g x) where
  parser = parserS

instance (Functor f, Functor g, Sum sum) => Functor (S sum f g) where
  map = mapS
  
instance (Algebra f a, Algebra g a, Sum sum) => Algebra (S sum f g) a where
  phi = phiS
  
--------------------------------------------------------------------------------

    





