module Data.Monoid.Applicative where

import qualified Data.Monoid.Transformer as MonoidTrans

import Control.Applicative (Applicative, pure, liftA2, )
import Data.Monoid (Monoid, mempty, )
import Data.Semigroup (Semigroup, (<>), )

{- |
Sequence applicative functors and combine their functorial results with '(<>)'.
-}
newtype T f a = Cons {forall (f :: * -> *) a. T f a -> f a
run :: f a}


instance (Applicative f, Semigroup a) => Semigroup (T f a) where
   Cons f a
x <> :: T f a -> T f a -> T f a
<> Cons f a
y = f a -> T f a
forall (f :: * -> *) a. f a -> T f a
Cons (f a -> T f a) -> f a -> T f a
forall a b. (a -> b) -> a -> b
$ (a -> a -> a) -> f a -> f a -> f a
forall a b c. (a -> b -> c) -> f a -> f b -> f c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 a -> a -> a
forall a. Semigroup a => a -> a -> a
(<>) f a
x f a
y

instance (Applicative f, Monoid a) => Monoid (T f a) where
   mempty :: T f a
mempty = f a -> T f a
forall (f :: * -> *) a. f a -> T f a
Cons (f a -> T f a) -> f a -> T f a
forall a b. (a -> b) -> a -> b
$ a -> f a
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
forall a. Monoid a => a
mempty

instance (Applicative f) => MonoidTrans.C (T f) where
   lift :: forall m. Monoid m => m -> T f m
lift = f m -> T f m
forall (f :: * -> *) a. f a -> T f a
Cons (f m -> T f m) -> (m -> f m) -> m -> T f m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m -> f m
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure