module Data.Monoid.Reader where

import qualified Data.Monoid.Transformer as MonoidTrans
import Data.Monoid (Monoid, mempty, )
import Data.Semigroup (Semigroup, (<>), )
import Data.Functor (Functor, fmap, )
import Data.Function (const, ($), (.), )

import Prelude ()


{- |
Could also be written as @Monoid.Applicative (Monad.Trans.Reader r) a@.
-}
newtype T r a = Cons {forall r a. T r a -> r -> a
run :: r -> a}

pure :: a -> T r a
pure :: forall a r. a -> T r a
pure = (r -> a) -> T r a
forall r a. (r -> a) -> T r a
Cons ((r -> a) -> T r a) -> (a -> r -> a) -> a -> T r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> r -> a
forall a b. a -> b -> a
const

instance Semigroup a => Semigroup (T r a) where
   Cons r -> a
x <> :: T r a -> T r a -> T r a
<> Cons r -> a
y = (r -> a) -> T r a
forall r a. (r -> a) -> T r a
Cons ((r -> a) -> T r a) -> (r -> a) -> T r a
forall a b. (a -> b) -> a -> b
$ \r
r -> r -> a
x r
r a -> a -> a
forall a. Semigroup a => a -> a -> a
<> r -> a
y r
r

instance Monoid a => Monoid (T r a) where
   mempty :: T r a
mempty = a -> T r a
forall m. Monoid m => m -> T r m
forall (t :: * -> *) m. (C t, Monoid m) => m -> t m
MonoidTrans.lift a
forall a. Monoid a => a
mempty

instance MonoidTrans.C (T r) where
   lift :: forall m. Monoid m => m -> T r m
lift = (r -> m) -> T r m
forall r a. (r -> a) -> T r a
Cons ((r -> m) -> T r m) -> (m -> r -> m) -> m -> T r m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m -> r -> m
forall a b. a -> b -> a
const

instance Functor (T r) where
   fmap :: forall a b. (a -> b) -> T r a -> T r b
fmap a -> b
f (Cons r -> a
g) = (r -> b) -> T r b
forall r a. (r -> a) -> T r a
Cons (a -> b
f (a -> b) -> (r -> a) -> r -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. r -> a
g)