{-# LANGUAGE UndecidableInstances #-}
module Algebra.Monad.Reader (
  -- *** The Reader monad
  MonadReader(..),
  ReaderT,Reader,
  _readerT,_reader,
  ) where

import Algebra.Monad.Base
import Algebra.Monad.RWS

instance MonadReader r ((->) r) where
  ask = id ; local = (>>>)

{-| A simple Reader monad -}
newtype ReaderT r m a = ReaderT (RWST r Void Void m a) 
                      deriving (Functor,Unit,Applicative,Monad,MonadFix,
                                MonadTrans,MonadInternal,
                                MonadReader r,MonadCont,MonadList)
type Reader r a = ReaderT r Id a

instance MonadState s m => MonadState s (ReaderT r m) where
  get = get_ ; put = put_ ; modify = modify_
instance MonadWriter w m => MonadWriter w (ReaderT r m) where
  tell = tell_ ; listen = listen_ ; censor = censor_
deriving instance Semigroup (m (a,Void,Void)) => Semigroup (ReaderT r m a)
deriving instance Monoid (m (a,Void,Void)) => Monoid (ReaderT r m a)
deriving instance Ring (m (a,Void,Void)) => Ring (ReaderT r m a)

_readerT :: (Functor m,Functor m') => Iso (ReaderT r m a) (ReaderT r' m' b) (r -> m a) (r' -> m' b)
_readerT = iso readerT runReaderT
  where readerT f = ReaderT (RWST (\ ~(r,_) -> f r<&>(,zero,zero) ))
        runReaderT (ReaderT (RWST f)) r = f (r,zero) <&> \ ~(a,_,_) -> a
_reader :: Iso (Reader r a) (Reader r' b) (r -> a) (r' -> b)
_reader = _mapping _Id._readerT