{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.FX.Monad.Trans.HaltT (
HaltT(..)
, runHaltT
, Context(..)
, InputT(..)
, OutputT(..)
) where
import Data.Typeable (Typeable)
import Control.FX.EqIn
import Control.FX.Functor
import Control.FX.Monad
import Control.FX.Monad.Trans.Class
newtype HaltT
(mark :: * -> *)
(m :: * -> *)
(a :: *)
= HaltT
{ unHaltT :: m (Halt mark a)
} deriving (Typeable)
deriving instance
( Show (m (Halt mark a))
) => Show (HaltT mark m a)
instance
( Monad m, MonadIdentity mark
) => Functor (HaltT mark m)
where
fmap
:: (a -> b)
-> HaltT mark m a
-> HaltT mark m b
fmap f =
HaltT . fmap (fmap f) . unHaltT
instance
( Monad m, MonadIdentity mark
) => Applicative (HaltT mark m)
where
pure
:: a
-> HaltT mark m a
pure = HaltT . return . Step
(<*>)
:: HaltT mark m (a -> b)
-> HaltT mark m a
-> HaltT mark m b
(HaltT mf) <*> (HaltT mx) =
HaltT $ do
f' <- mf
case f' of
Halt -> return Halt
Step f -> do
x' <- mx
case x' of
Halt -> return Halt
Step x -> return (Step (f x))
instance
( Monad m, MonadIdentity mark
) => Monad (HaltT mark m)
where
return
:: a
-> HaltT mark m a
return = HaltT . return . Step
(>>=)
:: HaltT mark m a
-> (a -> HaltT mark m b)
-> HaltT mark m b
(HaltT x) >>= f =
HaltT $ do
a' <- x
case a' of
Halt -> return Halt
Step a -> unHaltT $ f a
instance
( Central c, MonadIdentity mark
) => Commutant (HaltT mark c)
where
commute
:: ( Applicative f )
=> HaltT mark c (f a)
-> f (HaltT mark c a)
commute = fmap HaltT . commute . fmap commute . unHaltT
instance
( Central c, MonadIdentity mark
) => Central (HaltT mark c)
instance
( MonadIdentity mark
) => MonadTrans (HaltT mark)
where
lift
:: ( Monad m )
=> m a
-> HaltT mark m a
lift x = HaltT (x >>= (return . Step))
instance
( MonadIdentity mark
) => MonadFunctor (HaltT mark)
where
hoist
:: ( Monad m, Monad n )
=> ( forall u. m u -> n u )
-> HaltT mark m a
-> HaltT mark n a
hoist f = HaltT . f . unHaltT
instance
( EqIn m
) => EqIn (HaltT mark m)
where
newtype Context (HaltT mark m)
= HaltTCtx
{ unHaltTCtx :: (mark (), Context m)
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (HaltT mark m)
-> HaltT mark m a
-> HaltT mark m a
-> Bool
eqIn (HaltTCtx (_,h)) (HaltT x) (HaltT y) =
eqIn h x y
deriving instance
( Eq (mark ()), Eq (Context m)
) => Eq (Context (HaltT mark m))
deriving instance
( Show (mark ()), Show (Context m)
) => Show (Context (HaltT mark m))
instance
( MonadIdentity mark
) => RunMonadTrans (HaltT mark)
where
newtype InputT (HaltT mark)
= HaltTIn
{ unHaltTIn :: mark ()
} deriving (Typeable)
newtype OutputT (HaltT mark) a
= HaltTOut
{ unHaltTOut :: Halt mark a
} deriving (Eq, Show, Typeable)
runT
:: ( Monad m )
=> InputT (HaltT mark)
-> HaltT mark m a
-> m (OutputT (HaltT mark) a)
runT _ (HaltT x) = fmap HaltTOut x
runHaltT
:: ( Monad m, MonadIdentity mark )
=> HaltT mark m a
-> m (Halt mark a)
runHaltT =
fmap unHaltTOut . runT (HaltTIn $ pure ())
deriving instance
( Eq (mark ())
) => Eq (InputT (HaltT mark))
deriving instance
( Show (mark ())
) => Show (InputT (HaltT mark))
instance
( MonadIdentity mark
) => Functor (OutputT (HaltT mark))
where
fmap f (HaltTOut x) = HaltTOut (fmap f x)
instance
( MonadIdentity mark
) => Applicative (OutputT (HaltT mark))
where
pure = HaltTOut . pure
(HaltTOut f) <*> (HaltTOut x) =
HaltTOut (f <*> x)
instance
( MonadIdentity mark
) => LiftCatch (HaltT mark)
where
liftCatch
:: ( Monad m )
=> Catch e m (OutputT (HaltT mark) a)
-> Catch e (HaltT mark m) a
liftCatch catch x h = HaltT $
fmap unHaltTOut $ catch
(fmap HaltTOut $ unHaltT x)
(fmap HaltTOut . unHaltT . h)
instance
( MonadIdentity mark
) => LiftDraft (HaltT mark)
where
liftDraft
:: ( Monad m )
=> Draft w m (OutputT (HaltT mark) a)
-> Draft w (HaltT mark m) a
liftDraft draft =
HaltT . fmap unHaltTOut . fmap commute . draft . fmap HaltTOut . unHaltT
instance
( MonadIdentity mark
) => LiftLocal (HaltT mark)
where
liftLocal
:: ( Monad m )
=> Local r m (OutputT (HaltT mark) a)
-> Local r (HaltT mark m) a
liftLocal local f =
HaltT . fmap unHaltTOut . local f . fmap HaltTOut . unHaltT
instance {-# OVERLAPPING #-}
( Monad m, MonadIdentity mark
) => MonadHalt mark (HaltT mark m)
where
halt
:: mark ()
-> HaltT mark m a
halt = HaltT . return . halt
instance {-# OVERLAPPABLE #-}
( MonadHalt mark m, MonadIdentity mark, MonadIdentity mark1
) => MonadHalt mark (HaltT mark1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadReadOnly mark r m
) => MonadReadOnly mark r (HaltT mark1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadWriteOnly mark w m, Monoid w
) => MonadWriteOnly mark w (HaltT mark1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadState mark s m
) => MonadState mark s (HaltT mark1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadExcept mark e m
) => MonadExcept mark e (HaltT mark1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadPrompt mark p m
) => MonadPrompt mark p (HaltT mark1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadAppendOnly mark w m, Monoid w
) => MonadAppendOnly mark w (HaltT mark1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadWriteOnce mark w m
) => MonadWriteOnce mark w (HaltT mark1 m)