module Glazier.Gadget where
import Control.Applicative
import Control.Lens
import qualified Control.Monad.Fail as Fail
import Control.Monad.Fix (MonadFix)
import Control.Monad.Morph
import Control.Monad.Reader
import Control.Monad.State.Strict
import Data.Semigroup
newtype GadgetT a s m c = GadgetT
{ runGadgetT :: ReaderT a (StateT s m) c
} deriving ( MonadState s
, MonadReader a
, Monad
, Applicative
, Functor
, Fail.MonadFail
, Alternative
, MonadPlus
, MonadFix
, MonadIO
)
makeWrapped ''GadgetT
type Gadget a s = GadgetT a s Identity
_GadgetT :: Iso (GadgetT a s m c) (GadgetT a' s' m' c') (a -> s -> m (c, s)) (a' -> s' -> m' (c', s'))
_GadgetT = _Wrapping GadgetT . iso runReaderT ReaderT . iso (runStateT .) (StateT .)
_GadgetT' :: Iso' (GadgetT a s m c) (a -> s -> m (c, s))
_GadgetT' = _GadgetT
mkGadgetT' :: (a -> s -> m (c, s)) -> GadgetT a s m c
mkGadgetT' = review _GadgetT
runGadgetT' :: GadgetT a s m c -> (a -> s -> m (c, s))
runGadgetT' = view _GadgetT
belowGadgetT ::
((a -> s -> m (c, s)) -> a' -> s' -> m' (c', s'))
-> GadgetT a s m c -> GadgetT a' s' m' c'
belowGadgetT f = _GadgetT %~ f
underGadgetT
:: (ReaderT a (StateT s m) c -> ReaderT a' (StateT s' m') c')
-> GadgetT a s m c
-> GadgetT a' s' m' c'
underGadgetT f = _Wrapping GadgetT %~ f
overGadgetT
:: (GadgetT a s m c -> GadgetT a' s' m' c')
-> ReaderT a (StateT s m) c
-> ReaderT a' (StateT s' m') c'
overGadgetT f = _Unwrapping GadgetT %~ f
aboveGadgetT ::
(GadgetT a s m c -> GadgetT a' s' m' c')
-> (a -> s -> m (c, s)) -> a' -> s' -> m' (c', s')
aboveGadgetT f = from _GadgetT %~ f
instance MonadTrans (GadgetT a s) where
lift = GadgetT . lift . lift
instance MFunctor (GadgetT a s) where
hoist f (GadgetT m) = GadgetT (hoist (hoist f) m)
instance (Monad m, Semigroup c) => Semigroup (GadgetT a s m c) where
(GadgetT f) <> (GadgetT g) = GadgetT $ (<>) <$> f <*> g
instance (Monad m, Monoid c) => Monoid (GadgetT a s m c) where
mempty = GadgetT $ pure mempty
(GadgetT f) `mappend` (GadgetT g) = GadgetT $ mappend <$> f <*> g
type instance Zoomed (GadgetT a s m) = Zoomed (ReaderT a (StateT s m))
instance Monad m => Zoom (GadgetT a s m) (GadgetT a t m) s t where
zoom l = GadgetT . zoom l . runGadgetT
type instance Magnified (GadgetT a s m) = Magnified (ReaderT a (StateT s m))
instance Monad m => Magnify (GadgetT a s m) (GadgetT b s m) a b where
magnify l = GadgetT . magnify l . runGadgetT