{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Swagger.Declare where
import Prelude ()
import Prelude.Compat
import Control.Monad
import Control.Monad.Cont (ContT)
import Control.Monad.List (ListT)
import Control.Monad.Reader (ReaderT)
import Control.Monad.Trans
import Control.Monad.Trans.Except (ExceptT)
import Control.Monad.Trans.Identity (IdentityT)
import Control.Monad.Trans.Maybe (MaybeT)
import Control.Monad.Trans.State.Lazy as Lazy
import Control.Monad.Trans.State.Strict as Strict
import Control.Monad.Trans.RWS.Lazy as Lazy
import Control.Monad.Trans.RWS.Strict as Strict
import Control.Monad.Trans.Writer.Lazy as Lazy
import Control.Monad.Trans.Writer.Strict as Strict
import Data.Functor.Identity
newtype DeclareT d m a = DeclareT { runDeclareT :: d -> m (d, a) }
deriving (Functor)
instance (Applicative m, Monad m, Monoid d) => Applicative (DeclareT d m) where
pure x = DeclareT (\_ -> pure (mempty, x))
DeclareT df <*> DeclareT dx = DeclareT $ \d -> do
~(d', f) <- df d
~(d'', x) <- dx (mappend d d')
return (mappend d' d'', f x)
instance (Applicative m, Monad m, Monoid d) => Monad (DeclareT d m) where
return x = DeclareT (\_ -> pure (mempty, x))
DeclareT dx >>= f = DeclareT $ \d -> do
~(d', x) <- dx d
~(d'', y) <- runDeclareT (f x) (mappend d d')
return (mappend d' d'', y)
instance Monoid d => MonadTrans (DeclareT d) where
lift m = DeclareT (\_ -> (,) mempty `liftM` m)
class (Applicative m, Monad m) => MonadDeclare d m | m -> d where
declare :: d -> m ()
look :: m d
instance (Applicative m, Monad m, Monoid d) => MonadDeclare d (DeclareT d m) where
declare d = DeclareT (\_ -> return (d, ()))
look = DeclareT (\d -> return (mempty, d))
liftDeclare :: MonadDeclare d m => Declare d a -> m a
liftDeclare da = do
(d', a) <- looks (runDeclare da)
declare d'
pure a
looks :: MonadDeclare d m => (d -> a) -> m a
looks f = f <$> look
evalDeclareT :: Monad m => DeclareT d m a -> d -> m a
evalDeclareT (DeclareT f) d = snd `liftM` f d
execDeclareT :: Monad m => DeclareT d m a -> d -> m d
execDeclareT (DeclareT f) d = fst `liftM` f d
undeclareT :: (Monad m, Monoid d) => DeclareT d m a -> m a
undeclareT = flip evalDeclareT mempty
type Declare d = DeclareT d Identity
runDeclare :: Declare d a -> d -> (d, a)
runDeclare m = runIdentity . runDeclareT m
evalDeclare :: Declare d a -> d -> a
evalDeclare m = runIdentity . evalDeclareT m
execDeclare :: Declare d a -> d -> d
execDeclare m = runIdentity . execDeclareT m
undeclare :: Monoid d => Declare d a -> a
undeclare = runIdentity . undeclareT
instance MonadDeclare d m => MonadDeclare d (ContT r m) where
declare = lift . declare
look = lift look
instance MonadDeclare d m => MonadDeclare d (ExceptT e m) where
declare = lift . declare
look = lift look
instance MonadDeclare d m => MonadDeclare d (IdentityT m) where
declare = lift . declare
look = lift look
instance MonadDeclare d m => MonadDeclare d (MaybeT m) where
declare = lift . declare
look = lift look
instance MonadDeclare d m => MonadDeclare d (ReaderT r m) where
declare = lift . declare
look = lift look
instance (Monoid w, MonadDeclare d m) => MonadDeclare d (Lazy.RWST r w s m) where
declare = lift . declare
look = lift look
instance (Monoid w, MonadDeclare d m) => MonadDeclare d (Strict.RWST r w s m) where
declare = lift . declare
look = lift look
instance MonadDeclare d m => MonadDeclare d (Lazy.StateT s m) where
declare = lift . declare
look = lift look
instance MonadDeclare d m => MonadDeclare d (Strict.StateT s m) where
declare = lift . declare
look = lift look
instance (Monoid w, MonadDeclare d m) => MonadDeclare d (Lazy.WriterT w m) where
declare = lift . declare
look = lift look
instance (Monoid w, MonadDeclare d m) => MonadDeclare d (Strict.WriterT w m) where
declare = lift . declare
look = lift look