{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Control.FX.Monad.Trans.Trans.Data.StackTT (
StackTT(..)
, runStackTT
, Context(..)
, InputTT(..)
, OutputTT(..)
) where
import Data.Typeable (Typeable, Proxy)
import Control.FX
import Control.FX.Structure.Stack
import Control.FX.Monad.Data.Class
import Control.FX.Monad.Trans.Data.StackT
newtype StackTT
(mark :: * -> *)
(f :: * -> *)
(d :: *)
(t :: (* -> *) -> * -> *)
(m :: * -> *)
(a :: *)
= StackTT
{ unStackTT :: StackT mark f d (t m) a
} deriving
( Show, Typeable, Functor, Applicative, Monad )
instance
( MonadTrans t, MonadIdentity mark
) => MonadTrans (StackTT mark f d t)
where
lift
:: ( Monad m )
=> m a
-> StackTT mark f d t m a
lift = StackTT . lift . lift
instance
( MonadFunctor t, MonadIdentity mark
) => MonadFunctor (StackTT mark f d t)
where
hoist
:: ( Monad m, Monad n )
=> (forall u. m u -> n u)
-> StackTT mark f d t m a
-> StackTT mark f d t n a
hoist f = StackTT . hoist (hoist f) . unStackTT
instance
( MonadIdentity mark
) => MonadTransTrans (StackTT mark f d)
where
liftT
:: ( Monad m, MonadTrans t )
=> t m a
-> StackTT mark f d t m a
liftT = StackTT . lift
instance
( Monad m, MonadTrans t, MonadIdentity mark, Eq (f d)
, EqIn (t m), IsStack f
) => EqIn (StackTT mark f d t m)
where
newtype Context (StackTT mark f d t m)
= StackTTCtx
{ unStackTTCtx :: (mark (f d), Context (t m))
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (StackTT mark f d t m)
-> StackTT mark f d t m a
-> StackTT mark f d t m a
-> Bool
eqIn (StackTTCtx (v,h)) x y =
eqIn h
(fmap unStackTTOut $ runTT (StackTTIn v) x)
(fmap unStackTTOut $ runTT (StackTTIn v) y)
deriving instance
( Eq (mark (f d)), Eq (Context (t m))
) => Eq (Context (StackTT mark f d t m))
deriving instance
( Show (mark (f d)), Show (Context (t m))
) => Show (Context (StackTT mark f d t m))
instance
( MonadIdentity mark, IsStack f
) => RunMonadTransTrans (StackTT mark f d)
where
newtype InputTT (StackTT mark f d) m
= StackTTIn
{ unStackTTIn :: mark (f d)
} deriving (Typeable)
newtype OutputTT (StackTT mark f d) a
= StackTTOut
{ unStackTTOut :: Pair (mark (f d)) a
} deriving (Typeable)
runTT
:: ( Monad m, MonadTrans t )
=> InputTT (StackTT mark f d) m
-> StackTT mark f d t m a
-> t m (OutputTT (StackTT mark f d) a)
runTT (StackTTIn s) =
fmap (StackTTOut . unStackTOut)
. runT (StackTIn s) . unStackTT
deriving instance
( Eq (mark (f d))
) => Eq (InputTT (StackTT mark f d) m)
deriving instance
( Show (mark (f d))
) => Show (InputTT (StackTT mark f d) m)
deriving instance
( Eq (mark (f d)), Eq a
) => Eq (OutputTT (StackTT mark f d) a)
deriving instance
( Show (mark (f d)), Show a
) => Show (OutputTT (StackTT mark f d) a)
runStackTT
:: ( MonadIdentity mark, Monad m, MonadTrans t, IsStack f )
=> mark (f d)
-> StackTT mark f d t m a
-> t m (Pair (mark (f d)) a)
runStackTT s = fmap unStackTTOut . runTT (StackTTIn s)
instance
( MonadIdentity mark, IsStack f
) => LiftCatchT (StackTT mark f d)
where
liftCatchT
:: forall m t e
. ( Monad m, MonadTrans t )
=> (forall x. Catch e (t m) (OutputTT (StackTT mark f d) x))
-> (forall x. Catch e (StackTT mark f d t m) x)
liftCatchT catch x h =
let
catch' :: Catch e (t m) (OutputT (StackT mark f d) x)
catch' y g =
fmap (StackTOut . unStackTTOut) $ catch
(fmap (StackTTOut . unStackTOut) y)
(fmap (StackTTOut . unStackTOut) . g)
in
StackTT $
liftCatch catch' (unStackTT x) (unStackTT . h)
instance
( MonadIdentity mark, IsStack f
) => LiftDraftT (StackTT mark f d)
where
liftDraftT
:: forall m t w
. ( Monad m, MonadTrans t, Monoid w )
=> (forall x. Draft w (t m) (OutputTT (StackTT mark f d) x))
-> (forall x. Draft w (StackTT mark f d t m) x)
liftDraftT draft =
let
draft' :: Draft w (t m) (OutputT (StackT mark f d) x)
draft' =
fmap (fmap (StackTOut . unStackTTOut))
. draft . fmap (StackTTOut . unStackTOut)
in
StackTT . liftDraft draft' . unStackTT
instance
( MonadIdentity mark, IsStack f
) => LiftLocalT (StackTT mark f d)
where
liftLocalT
:: forall m t r
. ( Monad m, MonadTrans t )
=> (forall x. Local r (t m) (OutputTT (StackTT mark f d) x))
-> (forall x. Local r (StackTT mark f d t m) x)
liftLocalT local f =
let
local' :: Local r (t m) (OutputT (StackT mark f d) x)
local' g =
fmap (StackTOut . unStackTTOut)
. local g . fmap (StackTTOut . unStackTOut)
in
StackTT . liftLocal local' f . unStackTT
instance {-# OVERLAPPING #-}
( Monad m, MonadTrans t, MonadIdentity mark, IsStack f
) => MonadStack mark f d (StackTT mark f d t m)
where
push
:: Proxy f
-> mark d
-> StackTT mark f d t m ()
push proxy = StackTT . push proxy
pop
:: Proxy f
-> StackTT mark f d t m (mark (Maybe d))
pop proxy = StackTT $ pop proxy
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t, MonadIdentity mark, MonadIdentity mark1
, forall x. (Monad x) => MonadStack mark f d (t x), IsStack f
) => MonadStack mark f d (StackTT mark1 f1 d1 t m)
where
push
:: Proxy f
-> mark d
-> StackTT mark1 f1 d1 t m ()
push proxy = StackTT . lift . push proxy
pop
:: Proxy f
-> StackTT mark1 f1 d1 t m (mark (Maybe d))
pop proxy = StackTT $ lift $ pop proxy
instance
( Monad m, MonadTrans t, MonadIdentity mark, MonadIdentity mark1
, forall x. (Monad x) => MonadState mark s (t x), IsStack f
) => MonadState mark s (StackTT mark1 f d1 t m)
where
get
:: StackTT mark1 f d1 t m (mark s)
get = StackTT $ lift get
put
:: mark s
-> StackTT mark1 f d1 t m ()
put = StackTT . lift . put
instance
( Monad m, MonadTrans t, MonadIdentity mark, MonadIdentity mark1
, forall x. (Monad x) => MonadExcept mark e (t x), IsStack f
) => MonadExcept mark e (StackTT mark1 f d t m)
where
throw
:: mark e
-> StackTT mark1 f d t m a
throw = StackTT . lift . throw
catch
:: StackTT mark1 f d t m a
-> (mark e -> StackTT mark1 f d t m a)
-> StackTT mark1 f d t m a
catch = liftCatchT catch
instance
( Monad m, MonadTrans t, MonadIdentity mark, MonadIdentity mark1, Monoid w
, forall x. (Monad x) => MonadWriteOnly mark w (t x), IsStack f
) => MonadWriteOnly mark w (StackTT mark1 f d t m)
where
tell
:: mark w
-> StackTT mark1 f d t m ()
tell = StackTT . lift . tell
draft
:: StackTT mark1 f d t m a
-> StackTT mark1 f d t m (Pair (mark w) a)
draft = liftDraftT draft
instance
( Monad m, MonadTrans t, MonadIdentity mark, MonadIdentity mark1, Monoid w
, forall x. (Monad x) => MonadAppendOnly mark w (t x), IsStack f
) => MonadAppendOnly mark w (StackTT mark1 f d t m)
where
jot
:: mark w
-> StackTT mark1 f d t m ()
jot = StackTT . lift . jot
look
:: StackTT mark1 f d t m (mark w)
look = StackTT $ lift look
instance
( Monad m, MonadTrans t, MonadIdentity mark, MonadIdentity mark1
, forall x. (Monad x) => MonadWriteOnce mark w (t x), IsStack f
) => MonadWriteOnce mark w (StackTT mark1 f d t m)
where
etch
:: mark w
-> StackTT mark1 f d t m Bool
etch = StackTT . lift . etch
press
:: StackTT mark1 f d t m (Maybe (mark w))
press = StackTT $ lift press
instance
( Monad m, MonadTrans t, MonadIdentity mark, MonadIdentity mark1
, forall x. (Monad x) => MonadReadOnly mark r (t x), IsStack f
) => MonadReadOnly mark r (StackTT mark1 f d t m)
where
ask
:: StackTT mark1 f d t m (mark r)
ask = StackTT $ lift ask
local
:: (mark r -> mark r)
-> StackTT mark1 f d t m a
-> StackTT mark1 f d t m a
local = liftLocalT local
instance
( Monad m, MonadTrans t, MonadIdentity mark, MonadIdentity mark1
, forall x. (Monad x) => MonadPrompt mark p (t x), IsStack f
) => MonadPrompt mark p (StackTT mark1 f d t m)
where
prompt
:: mark (p a)
-> StackTT mark1 f d t m (mark a)
prompt = StackTT . lift . prompt
instance
( Monad m, MonadTrans t, MonadIdentity mark1, MonadIdentity mark
, forall x. (Monad x) => MonadHalt mark (t x), IsStack f
) => MonadHalt mark (StackTT mark1 f d t m)
where
halt
:: mark ()
-> StackTT mark1 f d t m a
halt = StackTT . lift . halt