module Data.Monoid.Endo.FromEndo
(
FromEndo(..)
, fromEndoWith
, fromEndoWithF
, fromDualEndoWith
, fromDualEndoWithF
, fromEndoTo
, fromDualEndoTo
)
where
import Control.Monad (Monad)
import Data.Function ((.), id)
import Data.Functor (Functor(fmap))
import Data.Monoid (Dual(Dual, getDual), Endo(Endo, appEndo), Monoid)
import Control.Monad.Trans.Reader (ReaderT)
import Control.Monad.Trans.Reader as Reader (asks)
import Control.Monad.Trans.RWS.Lazy as Lazy (RWST)
import Control.Monad.Trans.RWS.Lazy as Lazy.RWS (modify)
import Control.Monad.Trans.RWS.Strict as Strict (RWST)
import Control.Monad.Trans.RWS.Strict as Strict.RWS (modify)
import Control.Monad.Trans.State.Lazy as Lazy (StateT)
import Control.Monad.Trans.State.Lazy as Lazy.State (modify)
import Control.Monad.Trans.State.Strict as Strict (StateT)
import Control.Monad.Trans.State.Strict as Strict.State (modify)
class FromEndo a where
type EndoOperatedOn a
fromEndo :: Endo (EndoOperatedOn a) -> a
fromDualEndo :: Dual (Endo (EndoOperatedOn a)) -> a
fromDualEndo = fromEndo . getDual
#ifdef HAVE_MINIMAL_PRAGMA
#endif
instance FromEndo (a -> a) where
type EndoOperatedOn (a -> a) = a
fromEndo = appEndo
fromDualEndo = appEndo . getDual
instance FromEndo (Endo a) where
type EndoOperatedOn (Endo a) = a
fromEndo = id
fromDualEndo = getDual
instance FromEndo e => FromEndo (Dual e) where
type EndoOperatedOn (Dual e) = EndoOperatedOn e
fromEndo = Dual . fromEndo
fromDualEndo = Dual . fromDualEndo
instance Monad f => FromEndo (ReaderT r f r) where
type EndoOperatedOn (ReaderT r f r) = r
fromEndo (Endo f) = Reader.asks f
instance (Monoid w, Monad f) => FromEndo (Lazy.RWST r w s f ()) where
type EndoOperatedOn (Lazy.RWST r w s f ()) = s
fromEndo (Endo f) = Lazy.RWS.modify f
instance (Monoid w, Monad f) => FromEndo (Strict.RWST r w s f ()) where
type EndoOperatedOn (Strict.RWST r w s f ()) = s
fromEndo (Endo f) = Strict.RWS.modify f
instance Monad f => FromEndo (Lazy.StateT s f ()) where
type EndoOperatedOn (Lazy.StateT s f ()) = s
fromEndo (Endo f) = Lazy.State.modify f
instance Monad f => FromEndo (Strict.StateT s f ()) where
type EndoOperatedOn (Strict.StateT s f ()) = s
fromEndo (Endo f) = Strict.State.modify f
fromEndoWith :: (FromEndo a, EndoOperatedOn a ~ c) => (a -> b) -> Endo c -> b
fromEndoWith = (. fromEndo)
fromEndoWithF
:: (Functor f, FromEndo a, EndoOperatedOn a ~ c)
=> (f a -> b) -> f (Endo c) -> b
fromEndoWithF = (. fmap fromEndo)
fromDualEndoWith
:: (FromEndo a, EndoOperatedOn a ~ c) => (a -> b) -> Dual (Endo c) -> b
fromDualEndoWith = (. fromDualEndo)
fromDualEndoWithF
:: (Functor f, FromEndo a, EndoOperatedOn a ~ c)
=> (f a -> b) -> f (Dual (Endo c)) -> b
fromDualEndoWithF = (. fmap fromDualEndo)
fromEndoTo :: FromEndo a => Endo (EndoOperatedOn a) -> proxy a -> a
fromEndoTo e _ = fromEndo e
fromDualEndoTo :: FromEndo a => Dual (Endo (EndoOperatedOn a)) -> proxy a -> a
fromDualEndoTo e _ = fromDualEndo e