{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Control.FX.Monad.Trans.Trans.HaltTT (
HaltTT(..)
, runHaltTT
, Context(..)
, InputTT(..)
, OutputTT(..)
) where
import Data.Typeable (Typeable)
import Control.FX.EqIn
import Control.FX.Functor
import Control.FX.Monad
import Control.FX.Monad.Trans
import Control.FX.Monad.Trans.Trans.Class
newtype HaltTT
(mark :: * -> *)
(t :: (* -> *) -> * -> *)
(m :: * -> *)
(a :: *)
= HaltTT
{ unHaltTT :: HaltT mark (t m) a
} deriving
( Typeable, Functor, Applicative, Monad )
deriving instance
( Show (t m (Halt mark a))
) => Show (HaltTT mark t m a)
instance
( MonadTrans t, MonadIdentity mark
) => MonadTrans (HaltTT mark t)
where
lift
:: ( Monad m )
=> m a
-> HaltTT mark t m a
lift = HaltTT . lift . lift
instance
( MonadFunctor t, MonadIdentity mark
) => MonadFunctor (HaltTT mark t)
where
hoist
:: ( Monad m, Monad n )
=> (forall u. m u -> n u)
-> HaltTT mark t m a
-> HaltTT mark t n a
hoist f = HaltTT . hoist (hoist f) . unHaltTT
instance
( MonadIdentity mark
) => MonadTransTrans (HaltTT mark)
where
liftT
:: ( Monad m, MonadTrans t )
=> t m a
-> HaltTT mark t m a
liftT = HaltTT . lift
instance
( Monad m, MonadTrans t, MonadIdentity mark
, EqIn (t m)
) => EqIn (HaltTT mark t m)
where
newtype Context (HaltTT mark t m)
= HaltTTCtx
{ unHaltTTCtx :: (mark (), Context (t m))
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (HaltTT mark t m)
-> HaltTT mark t m a
-> HaltTT mark t m a
-> Bool
eqIn (HaltTTCtx (v,h)) x y =
eqIn h
(fmap unHaltTTOut $ runTT (HaltTTIn v) x)
(fmap unHaltTTOut $ runTT (HaltTTIn v) y)
deriving instance
( Eq (mark ()), Eq (Context (t m))
) => Eq (Context (HaltTT mark t m))
deriving instance
( Show (mark ()), Show (Context (t m))
) => Show (Context (HaltTT mark t m))
instance
( MonadIdentity mark
) => RunMonadTransTrans (HaltTT mark)
where
newtype InputTT (HaltTT mark) m
= HaltTTIn
{ unHaltTTIn :: mark ()
} deriving (Typeable)
newtype OutputTT (HaltTT mark) a
= HaltTTOut
{ unHaltTTOut :: Halt mark a
} deriving (Typeable)
runTT
:: ( Monad m, MonadTrans t )
=> InputTT (HaltTT mark) m
-> HaltTT mark t m a
-> t m (OutputTT (HaltTT mark) a)
runTT (HaltTTIn x) =
fmap (HaltTTOut . unHaltTOut)
. runT (HaltTIn x) . unHaltTT
deriving instance
( Eq (mark ())
) => Eq (InputTT (HaltTT mark) m)
deriving instance
( Show (mark ())
) => Show (InputTT (HaltTT mark) m)
deriving instance
( Eq (mark ()), Eq a
) => Eq (OutputTT (HaltTT mark) a)
deriving instance
( Show (mark ()), Show a
) => Show (OutputTT (HaltTT mark) a)
runHaltTT
:: ( Monad m, MonadTrans t, MonadIdentity mark )
=> HaltTT mark t m a
-> t m (Halt mark a)
runHaltTT = fmap unHaltTTOut . runTT (HaltTTIn (pure ()))
instance
( MonadIdentity mark
) => LiftCatchT (HaltTT mark)
where
liftCatchT
:: forall m t e
. ( Monad m, MonadTrans t )
=> (forall x. Catch e (t m) (OutputTT (HaltTT mark) x))
-> (forall x. Catch e (HaltTT mark t m) x)
liftCatchT catch x h =
let
catch' :: Catch e (t m) (OutputT (HaltT mark) x)
catch' y g =
fmap (HaltTOut . unHaltTTOut) $ catch
(fmap (HaltTTOut . unHaltTOut) y)
(fmap (HaltTTOut . unHaltTOut) . g)
in
HaltTT $ liftCatch catch' (unHaltTT x) (unHaltTT . h)
instance
( MonadIdentity mark
) => LiftDraftT (HaltTT mark)
where
liftDraftT
:: forall m t w
. ( Monad m, MonadTrans t, Monoid w )
=> (forall x. Draft w (t m) (OutputTT (HaltTT mark) x))
-> (forall x. Draft w (HaltTT mark t m) x)
liftDraftT draft =
let
draft' :: Draft w (t m) (OutputT (HaltT mark) x)
draft' =
fmap (fmap (HaltTOut . unHaltTTOut))
. draft . fmap (HaltTTOut . unHaltTOut)
in
HaltTT . liftDraft draft' . unHaltTT
instance
( MonadIdentity mark
) => LiftLocalT (HaltTT mark)
where
liftLocalT
:: forall m t r
. ( Monad m, MonadTrans t )
=> (forall x. Local r (t m) (OutputTT (HaltTT mark) x))
-> (forall x. Local r (HaltTT mark t m) x)
liftLocalT local f =
let
local' :: Local r (t m) (OutputT (HaltT mark) x)
local' g =
fmap (HaltTOut . unHaltTTOut)
. local g . fmap (HaltTTOut . unHaltTOut)
in
HaltTT . liftLocal local' f . unHaltTT
instance {-# OVERLAPPING #-}
( Monad m, MonadTrans t, MonadIdentity mark
) => MonadHalt mark (HaltTT mark t m)
where
halt
:: mark ()
-> HaltTT mark t m a
halt = HaltTT . halt
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t, MonadIdentity mark, MonadIdentity mark1
, forall x. (Monad x) => MonadHalt mark (t x)
) => MonadHalt mark (HaltTT mark1 t m)
where
halt
:: mark ()
-> HaltTT mark1 t m a
halt = HaltTT . lift . halt
instance
( Monad m, MonadTrans t, MonadIdentity mark1
, MonadState mark s (t m)
) => MonadState mark s (HaltTT mark1 t m)
where
get
:: HaltTT mark1 t m (mark s)
get = HaltTT $ lift get
put
:: mark s
-> HaltTT mark1 t m ()
put = HaltTT . lift . put
instance
( Monad m, MonadTrans t, MonadIdentity mark1
, MonadExcept mark e (t m)
) => MonadExcept mark e (HaltTT mark1 t m)
where
throw
:: mark e
-> HaltTT mark1 t m a
throw = HaltTT . lift . throw
catch
:: HaltTT mark1 t m a
-> (mark e -> HaltTT mark1 t m a)
-> HaltTT mark1 t m a
catch = liftCatchT catch
instance
( Monad m, MonadTrans t, Monoid w, MonadIdentity mark1
, MonadWriteOnly mark w (t m)
) => MonadWriteOnly mark w (HaltTT mark1 t m)
where
tell
:: mark w
-> HaltTT mark1 t m ()
tell = HaltTT . lift . tell
draft
:: HaltTT mark1 t m a
-> HaltTT mark1 t m (Pair (mark w) a)
draft = liftDraftT draft
instance
( Monad m, MonadTrans t, Monoid w, MonadIdentity mark1
, MonadAppendOnly mark w (t m)
) => MonadAppendOnly mark w (HaltTT mark1 t m)
where
jot
:: mark w
-> HaltTT mark1 t m ()
jot = HaltTT . lift . jot
look
:: HaltTT mark1 t m (mark w)
look = HaltTT $ lift look
instance
( Monad m, MonadTrans t, MonadIdentity mark1
, MonadWriteOnce mark w (t m)
) => MonadWriteOnce mark w (HaltTT mark1 t m)
where
etch
:: mark w
-> HaltTT mark1 t m Bool
etch = HaltTT . lift . etch
press
:: HaltTT mark1 t m (Maybe (mark w))
press = HaltTT $ lift press
instance
( Monad m, MonadTrans t, MonadIdentity mark1
, MonadReadOnly mark r (t m)
) => MonadReadOnly mark r (HaltTT mark1 t m)
where
ask
:: HaltTT mark1 t m (mark r)
ask = HaltTT $ lift ask
local
:: (mark r -> mark r)
-> HaltTT mark1 t m a
-> HaltTT mark1 t m a
local = liftLocalT local
instance
( Monad m, MonadTrans t, MonadIdentity mark1
, MonadPrompt mark p (t m)
) => MonadPrompt mark p (HaltTT mark1 t m)
where
prompt
:: mark (p a)
-> HaltTT mark1 t m (mark a)
prompt = HaltTT . lift . prompt