#ifdef LANGUAGE_DeriveDataTypeable
#endif
#if __GLASGOW_HASKELL__ >= 706
#endif
#if __GLASGOW_HASKELL__ >= 702 && __GLASGOW_HASKELL__ < 710
#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
untag :: Tagged s b -> b
untag = runIdentity . untagT
proxy :: Tagged s b -> Proxy s -> b
proxy x _ = untag x
unproxy :: (Proxy s -> a) -> Tagged s a
unproxy f = TagT (return $ f Proxy)
tagSelf :: a -> Tagged a a
tagSelf = TagT . return
untagSelf :: Tagged a a -> a
untagSelf = untag
tagWith :: proxy s -> a -> Tagged s a
tagWith _ = TagT . return
witness :: Tagged a b -> a -> b
witness x _ = untag x
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)
b <$ (TagT x) = TagT (b <$ x)
instance Contravariant m => Contravariant (TaggedT s m) where
contramap f (TagT x) = TagT (contramap f x)
instance Apply m => Apply (TaggedT s m) where
TagT f <.> TagT x = TagT (f <.> x)
TagT f .> TagT x = TagT (f .> x)
TagT f <. TagT x = TagT (f <. x)
instance Applicative m => Applicative (TaggedT s m) where
pure = TagT . pure
TagT f <*> TagT x = TagT (f <*> x)
TagT f *> TagT x = TagT (f *> x)
TagT f <* TagT x = TagT (f <* x)
instance Bind m => Bind (TaggedT s m) where
TagT m >>- k = TagT (m >>- untagT . k)
instance Monad m => Monad (TaggedT s m) where
return = TagT . return
TagT m >>= k = TagT (m >>= untagT . k)
TagT m >> TagT n = TagT (m >> n)
instance Alt m => Alt (TaggedT s m) where
TagT a <!> TagT b = TagT (a <!> b)
instance Alternative m => Alternative (TaggedT s m) where
empty = TagT empty
TagT a <|> TagT b = TagT (a <|> b)
instance Plus m => Plus (TaggedT s m) where
zero = TagT zero
instance MonadPlus m => MonadPlus (TaggedT s m) where
mzero = TagT mzero
mplus (TagT a) (TagT b) = TagT (mplus a b)
instance MonadFix m => MonadFix (TaggedT s m) where
mfix f = TagT $ mfix (untagT . f)
instance MonadTrans (TaggedT s) where
lift = TagT
instance MonadIO m => MonadIO (TaggedT s m) where
liftIO = lift . liftIO
instance MonadWriter w m => MonadWriter w (TaggedT s m) where
#if MIN_VERSION_mtl(2,1,0)
writer = lift . writer
#endif
tell = lift . tell
listen = lift . listen . untagT
pass = lift . pass . untagT
instance MonadReader r m => MonadReader r (TaggedT s m) where
ask = lift ask
local f = lift . local f . untagT
#if MIN_VERSION_mtl(2,1,0)
reader = lift . reader
#endif
instance MonadState t m => MonadState t (TaggedT s m) where
get = lift get
put = lift . put
#if MIN_VERSION_mtl(2,1,0)
state = lift . state
#endif
instance MonadCont m => MonadCont (TaggedT s m) where
callCC f = lift . callCC $ \k -> untagT (f (TagT . k))
instance Foldable f => Foldable (TaggedT s f) where
foldMap f (TagT x) = foldMap f x
fold (TagT x) = fold x
foldr f z (TagT x) = foldr f z x
foldl f z (TagT x) = foldl f z x
foldl1 f (TagT x) = foldl1 f x
foldr1 f (TagT x) = foldr1 f x
instance Traversable f => Traversable (TaggedT s f) where
traverse f (TagT x) = TagT <$> traverse f x
sequenceA (TagT x) = TagT <$> sequenceA x
mapM f (TagT x) = liftM TagT (mapM f x)
sequence (TagT x) = liftM TagT (sequence x)
instance Distributive f => Distributive (TaggedT s f) where
distribute = TagT . distribute . fmap untagT
instance Extend f => Extend (TaggedT s f) where
extended f (TagT w) = TagT (extended (f . TagT) w)
instance Comonad w => Comonad (TaggedT s w) where
extract (TagT w) = extract w
duplicate (TagT w) = TagT (extend TagT w)
instance ComonadTrans (TaggedT s) where
lower (TagT w) = w
instance ComonadHoist (TaggedT s) where
cohoist f = TagT . f . untagT
instance MonadThrow m => MonadThrow (TaggedT s m) where
throwM e = lift $ throwM e
instance MonadCatch m => MonadCatch (TaggedT s m) where
catch m f = TagT (catch (untagT m) (untagT . f))
instance MonadMask m => MonadMask (TaggedT s m) where
mask a = TagT $ mask $ \u -> untagT (a $ q u)
where q u = TagT . u . untagT
uninterruptibleMask a = TagT $ uninterruptibleMask $ \u -> untagT (a $ q u)
where q u = TagT . u . untagT
tagT :: m b -> TaggedT s m b
tagT = TagT
retag :: TaggedT s m b -> TaggedT t m b
retag = TagT . untagT
mapTaggedT :: (m a -> n b) -> TaggedT s m a -> TaggedT s n b
mapTaggedT f = TagT . f . untagT
reflected :: forall s m a. (Applicative m, Reifies s a) => TaggedT s m a
reflected = TagT . pure . reflect $ (Proxy :: Proxy s)
reflectedM :: forall s m a. (Monad m, Reifies s a) => TaggedT s m a
reflectedM = TagT . return . reflect $ (Proxy :: Proxy s)
asTaggedTypeOf :: s -> TaggedT s m b -> s
asTaggedTypeOf = const
proxyT :: TaggedT s m b -> Proxy s -> m b
proxyT x _ = untagT x
unproxyT :: (Proxy s -> m a) -> TaggedT s m a
unproxyT f = TagT (f Proxy)
tagTSelf :: m a -> TaggedT a m a
tagTSelf = TagT
untagTSelf :: TaggedT a m a -> m a
untagTSelf = untagT
tagTWith :: proxy s -> m a -> TaggedT s m a
tagTWith _ = TagT
witnessT :: TaggedT a m b -> a -> m b
witnessT x _ = untagT x