{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE CPP #-}
#ifdef LANGUAGE_DeriveDataTypeable
{-# LANGUAGE DeriveDataTypeable #-}
#endif
#if __GLASGOW_HASKELL__ >= 706
{-# LANGUAGE PolyKinds #-}
#endif
#if __GLASGOW_HASKELL__ >= 702 && __GLASGOW_HASKELL__ < 710
{-# LANGUAGE Trustworthy #-}
#endif
module Data.Functor.Trans.Tagged
(
TaggedT(..), Tagged
, tag, tagT
, untag
, retag
, mapTaggedT
, reflected, reflectedM
, asTaggedTypeOf
, proxy, proxyT
, unproxy, unproxyT
, tagSelf, tagTSelf
, untagSelf, untagTSelf
, tagWith, tagTWith
, witness, witnessT
) where
#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 706)
import Prelude hiding (foldr, foldl, mapM, sequence, foldr1, foldl1)
#else
import Prelude hiding (catch, foldr, foldl, mapM, sequence, foldr1, foldl1)
#endif
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative (Alternative(..), Applicative(..), (<$), (<$>))
#else
import Control.Applicative (Alternative(..))
#endif
import Control.Monad (liftM, MonadPlus(..))
import Control.Monad.Catch (MonadCatch(..), MonadThrow(..), MonadMask(..))
import Control.Monad.Fix (MonadFix(..))
import Control.Monad.Identity (Identity, runIdentity)
import Control.Monad.Trans (MonadIO(..), MonadTrans(..))
import Control.Monad.Reader (MonadReader(..))
import Control.Monad.Writer (MonadWriter(..))
import Control.Monad.State (MonadState(..))
import Control.Monad.Cont (MonadCont(..))
import Control.Comonad.Trans.Class (ComonadTrans(..))
import Control.Comonad.Hoist.Class (ComonadHoist(..))
import Control.Comonad (Comonad(..))
import Data.Traversable (Traversable(..))
import Data.Typeable
import Data.Foldable (Foldable(..))
import Data.Distributive (Distributive(..))
import Data.Functor.Bind (Apply(..), Bind(..))
import Data.Functor.Extend (Extend(..))
import Data.Functor.Plus (Alt(..), Plus(..))
import Data.Functor.Contravariant (Contravariant(..))
#if !(defined(__GLASGOW_HASKELL__)) || __GLASGOW_HASKELL__ < 707
import Data.Proxy (Proxy(..))
#endif
import Data.Reflection (Reifies(..))
type Tagged s b = TaggedT s Identity b
tag :: b -> Tagged s b
tag = TagT . return
{-# INLINE tag #-}
untag :: Tagged s b -> b
untag = runIdentity . untagT
{-# INLINE untag #-}
proxy :: Tagged s b -> Proxy s -> b
proxy x _ = untag x
{-# INLINE proxy #-}
unproxy :: (Proxy s -> a) -> Tagged s a
unproxy f = TagT (return $ f Proxy)
{-# INLINE unproxy #-}
tagSelf :: a -> Tagged a a
tagSelf = TagT . return
{-# INLINE tagSelf #-}
untagSelf :: Tagged a a -> a
untagSelf = untag
{-# INLINE untagSelf #-}
tagWith :: proxy s -> a -> Tagged s a
tagWith _ = TagT . return
{-# INLINE tagWith #-}
witness :: Tagged a b -> a -> b
witness x _ = untag x
{-# INLINE witness #-}
newtype TaggedT s m b = TagT { untagT :: m b }
deriving ( Eq, Ord, Read, Show
#if __GLASGOW_HASKELL__ >= 707
, Typeable
#endif
)
instance Functor m => Functor (TaggedT s m) where
fmap f (TagT x) = TagT (fmap f x)
{-# INLINE fmap #-}
b <$ (TagT x) = TagT (b <$ x)
{-# INLINE (<$) #-}
instance Contravariant m => Contravariant (TaggedT s m) where
contramap f (TagT x) = TagT (contramap f x)
{-# INLINE contramap #-}
instance Apply m => Apply (TaggedT s m) where
TagT f <.> TagT x = TagT (f <.> x)
{-# INLINE (<.>) #-}
TagT f .> TagT x = TagT (f .> x)
{-# INLINE ( .>) #-}
TagT f <. TagT x = TagT (f <. x)
{-# INLINE (<. ) #-}
instance Applicative m => Applicative (TaggedT s m) where
pure = TagT . pure
{-# INLINE pure #-}
TagT f <*> TagT x = TagT (f <*> x)
{-# INLINE (<*>) #-}
TagT f *> TagT x = TagT (f *> x)
{-# INLINE ( *>) #-}
TagT f <* TagT x = TagT (f <* x)
{-# INLINE (<* ) #-}
instance Bind m => Bind (TaggedT s m) where
TagT m >>- k = TagT (m >>- untagT . k)
{-# INLINE (>>-) #-}
instance Monad m => Monad (TaggedT s m) where
return = TagT . return
{-# INLINE return #-}
TagT m >>= k = TagT (m >>= untagT . k)
{-# INLINE (>>=) #-}
TagT m >> TagT n = TagT (m >> n)
{-# INLINE (>>) #-}
instance Alt m => Alt (TaggedT s m) where
TagT a <!> TagT b = TagT (a <!> b)
{-# INLINE (<!>) #-}
instance Alternative m => Alternative (TaggedT s m) where
empty = TagT empty
{-# INLINE empty #-}
TagT a <|> TagT b = TagT (a <|> b)
{-# INLINE (<|>) #-}
instance Plus m => Plus (TaggedT s m) where
zero = TagT zero
{-# INLINE zero #-}
instance MonadPlus m => MonadPlus (TaggedT s m) where
mzero = TagT mzero
{-# INLINE mzero #-}
mplus (TagT a) (TagT b) = TagT (mplus a b)
{-# INLINE mplus #-}
instance MonadFix m => MonadFix (TaggedT s m) where
mfix f = TagT $ mfix (untagT . f)
{-# INLINE mfix #-}
instance MonadTrans (TaggedT s) where
lift = TagT
{-# INLINE lift #-}
instance MonadIO m => MonadIO (TaggedT s m) where
liftIO = lift . liftIO
{-# INLINE liftIO #-}
instance MonadWriter w m => MonadWriter w (TaggedT s m) where
#if MIN_VERSION_mtl(2,1,0)
writer = lift . writer
{-# INLINE writer #-}
#endif
tell = lift . tell
{-# INLINE tell #-}
listen = lift . listen . untagT
{-# INLINE listen #-}
pass = lift . pass . untagT
{-# INLINE pass #-}
instance MonadReader r m => MonadReader r (TaggedT s m) where
ask = lift ask
{-# INLINE ask #-}
local f = lift . local f . untagT
{-# INLINE local #-}
#if MIN_VERSION_mtl(2,1,0)
reader = lift . reader
{-# INLINE reader #-}
#endif
instance MonadState t m => MonadState t (TaggedT s m) where
get = lift get
{-# INLINE get #-}
put = lift . put
{-# INLINE put #-}
#if MIN_VERSION_mtl(2,1,0)
state = lift . state
{-# INLINE state #-}
#endif
instance MonadCont m => MonadCont (TaggedT s m) where
callCC f = lift . callCC $ \k -> untagT (f (TagT . k))
{-# INLINE callCC #-}
instance Foldable f => Foldable (TaggedT s f) where
foldMap f (TagT x) = foldMap f x
{-# INLINE foldMap #-}
fold (TagT x) = fold x
{-# INLINE fold #-}
foldr f z (TagT x) = foldr f z x
{-# INLINE foldr #-}
foldl f z (TagT x) = foldl f z x
{-# INLINE foldl #-}
foldl1 f (TagT x) = foldl1 f x
{-# INLINE foldl1 #-}
foldr1 f (TagT x) = foldr1 f x
{-# INLINE foldr1 #-}
instance Traversable f => Traversable (TaggedT s f) where
traverse f (TagT x) = TagT <$> traverse f x
{-# INLINE traverse #-}
sequenceA (TagT x) = TagT <$> sequenceA x
{-# INLINE sequenceA #-}
mapM f (TagT x) = liftM TagT (mapM f x)
{-# INLINE mapM #-}
sequence (TagT x) = liftM TagT (sequence x)
{-# INLINE sequence #-}
instance Distributive f => Distributive (TaggedT s f) where
distribute = TagT . distribute . fmap untagT
{-# INLINE distribute #-}
instance Extend f => Extend (TaggedT s f) where
extended f (TagT w) = TagT (extended (f . TagT) w)
{-# INLINE extended #-}
instance Comonad w => Comonad (TaggedT s w) where
extract (TagT w) = extract w
{-# INLINE extract #-}
duplicate (TagT w) = TagT (extend TagT w)
{-# INLINE duplicate #-}
instance ComonadTrans (TaggedT s) where
lower (TagT w) = w
{-# INLINE lower #-}
instance ComonadHoist (TaggedT s) where
cohoist f = TagT . f . untagT
{-# INLINE cohoist #-}
instance MonadThrow m => MonadThrow (TaggedT s m) where
throwM e = lift $ throwM e
{-# INLINE throwM #-}
instance MonadCatch m => MonadCatch (TaggedT s m) where
catch m f = TagT (catch (untagT m) (untagT . f))
{-# INLINE catch #-}
instance MonadMask m => MonadMask (TaggedT s m) where
mask a = TagT $ mask $ \u -> untagT (a $ q u)
where q u = TagT . u . untagT
{-# INLINE mask #-}
uninterruptibleMask a = TagT $ uninterruptibleMask $ \u -> untagT (a $ q u)
where q u = TagT . u . untagT
{-# INLINE uninterruptibleMask#-}
#if MIN_VERSION_exceptions(0,10,0)
generalBracket acquire release use = TagT $
generalBracket
(untagT acquire)
(\resource exitCase -> untagT (release resource exitCase))
(\resource -> untagT (use resource))
#endif
tagT :: m b -> TaggedT s m b
tagT = TagT
{-# INLINE tagT #-}
retag :: TaggedT s m b -> TaggedT t m b
retag = TagT . untagT
{-# INLINE retag #-}
mapTaggedT :: (m a -> n b) -> TaggedT s m a -> TaggedT s n b
mapTaggedT f = TagT . f . untagT
{-# INLINE mapTaggedT #-}
reflected :: forall s m a. (Applicative m, Reifies s a) => TaggedT s m a
reflected = TagT . pure . reflect $ (Proxy :: Proxy s)
{-# INLINE reflected #-}
reflectedM :: forall s m a. (Monad m, Reifies s a) => TaggedT s m a
reflectedM = TagT . return . reflect $ (Proxy :: Proxy s)
{-# INLINE reflectedM #-}
asTaggedTypeOf :: s -> TaggedT s m b -> s
asTaggedTypeOf = const
{-# INLINE asTaggedTypeOf #-}
proxyT :: TaggedT s m b -> Proxy s -> m b
proxyT x _ = untagT x
{-# INLINE proxyT #-}
unproxyT :: (Proxy s -> m a) -> TaggedT s m a
unproxyT f = TagT (f Proxy)
{-# INLINE unproxyT #-}
tagTSelf :: m a -> TaggedT a m a
tagTSelf = TagT
{-# INLINE tagTSelf #-}
untagTSelf :: TaggedT a m a -> m a
untagTSelf = untagT
{-# INLINE untagTSelf #-}
tagTWith :: proxy s -> m a -> TaggedT s m a
tagTWith _ = TagT
{-# INLINE tagTWith #-}
witnessT :: TaggedT a m b -> a -> m b
witnessT x _ = untagT x
{-# INLINE witnessT #-}