{-# LANGUAGE TypeOperators #-}
module Control.Applicative.Compose where

import Control.Applicative

-- | Type-level composition
newtype (f :+: g) a = Compose { decompose :: (f (g a)) }

instance (Functor f, Functor g) => Functor (f :+: g) where
  fmap f (Compose x) = Compose $ (fmap . fmap) f x

{- The composition of any two Applicatives is an idiom -}
instance (Applicative f, Applicative g) => Applicative (f :+: g) where
   pure x = Compose$ (pure pure) <*> (pure x)
   Compose fs <*> Compose xs = Compose $ pure (<*>) <*> fs <*> xs