{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.FX.Monad.Trans.ExceptT (
ExceptT(..)
, runExceptT
, Context(..)
, InputT(..)
, OutputT(..)
) where
import Data.Typeable (Typeable, typeOf)
import Control.Applicative (liftA2)
import Control.FX.EqIn
import Control.FX.Functor
import Control.FX.Monad
import Control.FX.Monad.Trans.Class
newtype ExceptT
(mark :: * -> *)
(e :: *)
(m :: * -> *)
(a :: *)
= ExceptT
{ unExceptT :: m (Except mark e a)
} deriving (Typeable)
deriving instance
( Show (m (Except mark e a))
) => Show (ExceptT mark e m a)
instance
( Monad m, MonadIdentity mark
) => Functor (ExceptT mark e m)
where
fmap
:: (a -> b)
-> ExceptT mark e m a
-> ExceptT mark e m b
fmap f = ExceptT . fmap (fmap f) . unExceptT
instance
( Monad m, MonadIdentity mark
) => Applicative (ExceptT mark e m)
where
pure
:: a
-> ExceptT mark e m a
pure = ExceptT . pure . pure
(<*>)
:: ExceptT mark e m (a -> b)
-> ExceptT mark e m a
-> ExceptT mark e m b
(ExceptT f) <*> (ExceptT x) =
ExceptT $ liftA2 (<*>) f x
instance
( Monad m, MonadIdentity mark
) => Monad (ExceptT mark e m)
where
return
:: a
-> ExceptT mark e m a
return = ExceptT . return . Accept
(>>=)
:: ExceptT mark e m a
-> (a -> ExceptT mark e m b)
-> ExceptT mark e m b
(ExceptT x) >>= f =
ExceptT $ do
a' <- x
case a' of
Except e -> return (Except e)
Accept a -> unExceptT $ f a
instance
( Central c, MonadIdentity mark
) => Commutant (ExceptT mark e c)
where
commute
:: ( Applicative f )
=> ExceptT mark e c (f a)
-> f (ExceptT mark e c a)
commute = fmap ExceptT . commute . fmap commute . unExceptT
instance
( Central c, MonadIdentity mark
) => Central (ExceptT mark e c)
instance
( MonadIdentity mark
) => MonadTrans (ExceptT mark e) where
lift
:: ( Monad m )
=> m a
-> ExceptT mark e m a
lift x = ExceptT (x >>= (return . pure))
instance
( MonadIdentity mark
) => MonadFunctor (ExceptT mark e) where
hoist
:: ( Monad m, Monad n )
=> ( forall u. m u -> n u )
-> ExceptT mark e m a
-> ExceptT mark e n a
hoist f = ExceptT . f . unExceptT
instance
( EqIn m, MonadIdentity mark, Eq e
) => EqIn (ExceptT mark e m)
where
newtype Context (ExceptT mark e m)
= ExceptTCtx
{ unExceptTCtx :: (mark (), Context m)
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (ExceptT mark e m)
-> ExceptT mark e m a
-> ExceptT mark e m a
-> Bool
eqIn (ExceptTCtx (_,h)) x y =
eqIn h (unExceptT x) (unExceptT y)
deriving instance
( Eq (mark ()), Eq (Context m)
) => Eq (Context (ExceptT mark e m))
deriving instance
( Show (mark ()), Show (Context m)
) => Show (Context (ExceptT mark e m))
instance
( MonadIdentity mark
) => RunMonadTrans (ExceptT mark e)
where
newtype InputT (ExceptT mark e)
= ExceptTIn
{ unExceptTIn :: mark ()
} deriving (Typeable)
newtype OutputT (ExceptT mark e) a
= ExceptTOut
{ unExceptTOut :: Except mark e a
} deriving (Eq, Show, Typeable)
runT
:: ( Monad m )
=> InputT (ExceptT mark e)
-> ExceptT mark e m a
-> m (OutputT (ExceptT mark e) a)
runT _ (ExceptT x) = fmap ExceptTOut x
runExceptT
:: ( Monad m, MonadIdentity mark )
=> ExceptT mark e m a
-> m (Except mark e a)
runExceptT =
fmap unExceptTOut . runT (ExceptTIn $ pure ())
deriving instance
( Eq (mark ())
) => Eq (InputT (ExceptT mark e))
deriving instance
( Show (mark ())
) => Show (InputT (ExceptT mark e))
instance
( MonadIdentity mark
) => Functor (OutputT (ExceptT mark e))
where
fmap f (ExceptTOut x) = ExceptTOut (fmap f x)
instance
( MonadIdentity mark
) => Applicative (OutputT (ExceptT mark e))
where
pure = ExceptTOut . pure
(ExceptTOut f) <*> (ExceptTOut x) =
ExceptTOut (f <*> x)
instance
( MonadIdentity mark
) => LiftCatch (ExceptT mark e)
where
liftCatch
:: ( Monad m )
=> Catch e2 m (OutputT (ExceptT mark e) a)
-> Catch e2 (ExceptT mark e m) a
liftCatch catch x h = ExceptT $
fmap unExceptTOut $ catch
(fmap ExceptTOut $ unExceptT x)
(fmap ExceptTOut . unExceptT . h)
instance
( MonadIdentity mark
) => LiftDraft (ExceptT mark e)
where
liftDraft
:: ( Monad m )
=> Draft w m (OutputT (ExceptT mark e) a)
-> Draft w (ExceptT mark e m) a
liftDraft draft =
ExceptT . fmap unExceptTOut . fmap commute . draft . fmap ExceptTOut . unExceptT
instance
( MonadIdentity mark
) => LiftLocal (ExceptT mark e)
where
liftLocal
:: ( Monad m )
=> Local r m (OutputT (ExceptT mark e) a)
-> Local r (ExceptT mark e m) a
liftLocal local f =
ExceptT . fmap unExceptTOut . local f . fmap ExceptTOut . unExceptT
instance {-# OVERLAPPING #-}
( Monad m, MonadIdentity mark
) => MonadExcept mark e (ExceptT mark e m)
where
throw
:: mark e
-> ExceptT mark e m a
throw = ExceptT . return . Except . unwrap
catch
:: ExceptT mark e m a
-> (mark e -> ExceptT mark e m a)
-> ExceptT mark e m a
catch (ExceptT x) h = ExceptT $ do
a <- x
case a of
Except e -> unExceptT $ h (pure e)
Accept z -> return (Accept z)
instance {-# OVERLAPPABLE #-}
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadExcept mark e m
) => MonadExcept mark e (ExceptT mark1 e1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1, Monoid w
, MonadWriteOnly mark w m
) => MonadWriteOnly mark w (ExceptT mark1 e m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadState mark s m
) => MonadState mark s (ExceptT mark1 e m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadReadOnly mark r m
) => MonadReadOnly mark r (ExceptT mark1 e m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadHalt mark m
) => MonadHalt mark (ExceptT mark1 e m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadPrompt mark p m
) => MonadPrompt mark p (ExceptT mark1 e m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1, Monoid w
, MonadAppendOnly mark w m
) => MonadAppendOnly mark w (ExceptT mark1 e m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadWriteOnce mark w m
) => MonadWriteOnce mark w (ExceptT mark1 e m)