{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE MultiParamTypeClasses #-}

-- |
-- Module      : App
-- License     : BSD3
-- Maintainer  : tbidne@gmail.com
-- Provides the main component used in this application.
module App
  ( AppT (..),
    mapAppT,
  )
where

import qualified Control.Monad.Reader as R

-- | Main component used in this application.
newtype AppT e m a = AppT {AppT e m a -> ReaderT e m a
runAppT :: R.ReaderT e m a}

instance Functor m => Functor (AppT e m) where
  fmap :: (a -> b) -> AppT e m a -> AppT e m b
fmap f :: a -> b
f (AppT m :: ReaderT e m a
m) = ReaderT e m b -> AppT e m b
forall e (m :: * -> *) a. ReaderT e m a -> AppT e m a
AppT ((a -> b) -> ReaderT e m a -> ReaderT e m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f ReaderT e m a
m)

instance Applicative f => Applicative (AppT e f) where
  pure :: a -> AppT e f a
pure = ReaderT e f a -> AppT e f a
forall e (m :: * -> *) a. ReaderT e m a -> AppT e m a
AppT (ReaderT e f a -> AppT e f a)
-> (a -> ReaderT e f a) -> a -> AppT e f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ReaderT e f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
  (AppT f :: ReaderT e f (a -> b)
f) <*> :: AppT e f (a -> b) -> AppT e f a -> AppT e f b
<*> (AppT m :: ReaderT e f a
m) = ReaderT e f b -> AppT e f b
forall e (m :: * -> *) a. ReaderT e m a -> AppT e m a
AppT (ReaderT e f (a -> b)
f ReaderT e f (a -> b) -> ReaderT e f a -> ReaderT e f b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReaderT e f a
m)

instance Monad m => Monad (AppT e m) where
  (AppT m :: ReaderT e m a
m) >>= :: AppT e m a -> (a -> AppT e m b) -> AppT e m b
>>= f :: a -> AppT e m b
f = ReaderT e m b -> AppT e m b
forall e (m :: * -> *) a. ReaderT e m a -> AppT e m a
AppT (ReaderT e m a
m ReaderT e m a -> (a -> ReaderT e m b) -> ReaderT e m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (AppT e m b -> ReaderT e m b
forall e (m :: * -> *) a. AppT e m a -> ReaderT e m a
runAppT (AppT e m b -> ReaderT e m b)
-> (a -> AppT e m b) -> a -> ReaderT e m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> AppT e m b
f))

instance R.MonadTrans (AppT e) where
  lift :: m a -> AppT e m a
lift = ReaderT e m a -> AppT e m a
forall e (m :: * -> *) a. ReaderT e m a -> AppT e m a
AppT (ReaderT e m a -> AppT e m a)
-> (m a -> ReaderT e m a) -> m a -> AppT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m a -> ReaderT e m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
R.lift

instance R.MonadIO m => R.MonadIO (AppT e m) where
  liftIO :: IO a -> AppT e m a
liftIO = m a -> AppT e m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
R.lift (m a -> AppT e m a) -> (IO a -> m a) -> IO a -> AppT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
R.liftIO

instance Monad m => R.MonadReader e (AppT e m) where
  ask :: AppT e m e
ask = ReaderT e m e -> AppT e m e
forall e (m :: * -> *) a. ReaderT e m a -> AppT e m a
AppT ReaderT e m e
forall r (m :: * -> *). MonadReader r m => m r
R.ask
  local :: (e -> e) -> AppT e m a -> AppT e m a
local = (e -> e) -> AppT e m a -> AppT e m a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
R.local
  reader :: (e -> a) -> AppT e m a
reader = (e -> a) -> AppT e m a
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
R.reader

-- | Transforms an 'AppT' e m a.
mapAppT ::
  (R.ReaderT e m a -> R.ReaderT e n b) ->
  AppT e m a ->
  AppT e n b
mapAppT :: (ReaderT e m a -> ReaderT e n b) -> AppT e m a -> AppT e n b
mapAppT f :: ReaderT e m a -> ReaderT e n b
f = ReaderT e n b -> AppT e n b
forall e (m :: * -> *) a. ReaderT e m a -> AppT e m a
AppT (ReaderT e n b -> AppT e n b)
-> (AppT e m a -> ReaderT e n b) -> AppT e m a -> AppT e n b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReaderT e m a -> ReaderT e n b
f (ReaderT e m a -> ReaderT e n b)
-> (AppT e m a -> ReaderT e m a) -> AppT e m a -> ReaderT e n b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AppT e m a -> ReaderT e m a
forall e (m :: * -> *) a. AppT e m a -> ReaderT e m a
runAppT