{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.FX.Monad.Trans.Data.StackT (
StackT(..)
, runStackT
, Context(..)
, InputT(..)
, OutputT(..)
) where
import Data.Typeable (Typeable, Proxy, typeOf)
import Control.FX
import Control.FX.Structure.Stack
import Control.FX.Monad.Data.Class
newtype StackT
(mark :: * -> *)
(f :: * -> *)
(d :: *)
(m :: * -> *)
(a :: *)
= StackT
{ unStackT :: f d -> m (Pair (f d) a)
} deriving (Typeable)
instance
( Typeable f, Typeable d, Typeable m, Typeable a, Typeable mark
) => Show (StackT mark f d m a)
where
show
:: StackT mark f d m a
-> String
show = show . typeOf
instance
( Monad m, MonadIdentity mark
) => Functor (StackT mark f d m)
where
fmap
:: (a -> b)
-> StackT mark f d m a
-> StackT mark f d m b
fmap f (StackT x) =
StackT $ \s1 -> do
Pair s2 a <- x s1
return $ Pair s2 (f a)
instance
( Monad m, MonadIdentity mark
) => Applicative (StackT mark f d m)
where
pure
:: a
-> StackT mark f d m a
pure x =
StackT $ \s -> pure $ Pair s x
(<*>)
:: StackT mark f d m (a -> b)
-> StackT mark f d m a
-> StackT mark f d m b
(StackT f) <*> (StackT x) =
StackT $ \s1 -> do
Pair s2 g <- f s1
Pair s3 a <- x s2
return $ Pair s3 (g a)
instance
( Monad m, MonadIdentity mark
) => Monad (StackT mark f d m)
where
return
:: a
-> StackT mark f d m a
return x =
StackT $ \s -> return $ Pair s x
(>>=)
:: StackT mark f d m a
-> (a -> StackT mark f d m b)
-> StackT mark f d m b
(StackT x) >>= f =
StackT $ \s1 -> do
Pair s2 a <- x s1
unStackT (f a) s2
instance
( MonadIdentity mark
) => MonadTrans (StackT mark f d)
where
lift
:: ( Monad m )
=> m a
-> StackT mark f d m a
lift x = StackT $ \s -> fmap (\a -> Pair s a) x
instance
( MonadIdentity mark
) => MonadFunctor (StackT mark f d)
where
hoist
:: ( Monad m, Monad n )
=> (forall u. m u -> n u)
-> StackT mark f d m a
-> StackT mark f d n a
hoist f (StackT x) =
StackT $ \s -> do
a <- f $ fmap slot2 (x s)
return $ Pair s a
instance
( MonadIdentity mark
) => ComposableT (StackT mark f d)
where
newtype (ComposeT (StackT mark f d) t2 m a) =
ComposeT_StackT
{ unComposeT_StackT :: StackT mark f d (t2 m) a
} deriving (Typeable)
toComposeT = ComposeT_StackT
unComposeT = unComposeT_StackT
instance {-# OVERLAPS #-}
( Monad m, MonadTrans t2, MonadIdentity mark, IsStack f
) => MonadStack mark f d (ComposeT (StackT mark f d) t2 m)
where
push
:: Proxy f
-> mark d
-> ComposeT (StackT mark f d) t2 m ()
push proxy = toComposeT . push proxy
pop
:: Proxy f
-> ComposeT (StackT mark f d) t2 m (mark (Maybe d))
pop proxy = toComposeT $ pop proxy
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t1, MonadTrans t2, MonadIdentity mark, ComposableT t1
, forall x. (Monad x) => MonadStack mark f d (t2 x), IsStack f
) => MonadStack mark f d (ComposeT t1 t2 m)
where
push
:: Proxy f
-> mark d
-> ComposeT t1 t2 m ()
push proxy = toComposeT . lift . push proxy
pop
:: Proxy f
-> ComposeT t1 t2 m (mark (Maybe d))
pop proxy = toComposeT $ lift $ pop proxy
instance
( MonadIdentity mark
) => OverableT (StackT mark f d)
where
newtype (OverTT (StackT mark f d) u t m a) =
OverTT_StackT
{ unOverTT_StackT :: StackT mark f d (u t m) a
} deriving (Typeable)
toOverTT = OverTT_StackT
unOverTT = unOverTT_StackT
instance {-# OVERLAPS #-}
( Monad m, MonadTrans t, IsStack f
, MonadTransTrans u, MonadIdentity mark
) => MonadStack mark f d (OverTT (StackT mark f d) u t m)
where
push
:: Proxy f
-> mark d
-> OverTT (StackT mark f d) u t m ()
push proxy = toOverTT . push proxy
pop
:: Proxy f
-> OverTT (StackT mark f d) u t m (mark (Maybe d))
pop proxy = toOverTT $ pop proxy
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t, MonadTrans v, OverableT v
, MonadTransTrans u, MonadIdentity mark, IsStack f
, forall x. (Monad x) => MonadStack mark f d (u t x)
) => MonadStack mark f d (OverTT v u t m)
where
push
:: Proxy f
-> mark d
-> OverTT v u t m ()
push proxy = toOverTT . lift . push proxy
pop
:: Proxy f
-> OverTT v u t m (mark (Maybe d))
pop proxy = toOverTT $ lift $ pop proxy
instance
( EqIn m, MonadIdentity mark, Eq (f d)
) => EqIn (StackT mark f d m)
where
newtype Context (StackT mark f d m)
= StackTCtx
{ unStackTCtx :: (mark (f d), Context m)
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (StackT mark f d m)
-> StackT mark f d m a
-> StackT mark f d m a
-> Bool
eqIn (StackTCtx (s,h)) (StackT x) (StackT y) =
eqIn h (x $ unwrap s) (y $ unwrap s)
deriving instance
( Eq (mark (f d)), Eq (Context m)
) => Eq (Context (StackT mark f d m))
deriving instance
( Show (mark (f d)), Show (Context m)
) => Show (Context (StackT mark f d m))
instance
( MonadIdentity mark
) => RunMonadTrans (StackT mark f d)
where
newtype InputT (StackT mark f d)
= StackTIn
{ unStackTIn :: mark (f d)
} deriving (Typeable)
newtype OutputT (StackT mark f d) a
= StackTOut
{ unStackTOut :: Pair (mark (f d)) a
} deriving (Typeable)
runT
:: ( Monad m )
=> InputT (StackT mark f d)
-> StackT mark f d m a
-> m (OutputT (StackT mark f d) a)
runT (StackTIn s) (StackT x) = do
Pair s1 a <- x (unwrap s)
return $ StackTOut $ Pair (pure s1) a
runStackT
:: ( Monad m, MonadIdentity mark )
=> mark (f d)
-> StackT mark f d m a
-> m (Pair (mark (f d)) a)
runStackT inp =
fmap unStackTOut . runT (StackTIn inp)
deriving instance
( Eq (mark (f d))
) => Eq (InputT (StackT mark f d))
deriving instance
( Show (mark (f d))
) => Show (InputT (StackT mark f d))
deriving instance
( Eq (mark (f d)), Eq a
) => Eq (OutputT (StackT mark f d) a)
deriving instance
( Show (mark (f d)), Show a
) => Show (OutputT (StackT mark f d) a)
instance
( MonadIdentity mark
) => LiftCatch (StackT mark f d)
where
liftCatch
:: ( Monad m )
=> Catch e m (OutputT (StackT mark f d) a)
-> Catch e (StackT mark f d m) a
liftCatch catch x h = StackT $ \s ->
fmap (bimap1 unwrap . unStackTOut) $ catch
(fmap (StackTOut . bimap1 pure) $ unStackT x s)
(\e -> fmap (StackTOut . bimap1 pure) $ unStackT (h e) s)
instance
( MonadIdentity mark
) => LiftDraft (StackT mark f d)
where
liftDraft
:: ( Monad m )
=> Draft w m (OutputT (StackT mark f d) a)
-> Draft w (StackT mark f d m) a
liftDraft draft x =
StackT $ \s -> do
Pair w (StackTOut (Pair s a)) <- draft $ fmap (StackTOut . bimap1 pure) $ unStackT x s
return $ Pair (unwrap s) (Pair w a)
instance
( MonadIdentity mark
) => LiftLocal (StackT mark f d)
where
liftLocal
:: ( Monad m )
=> Local r m (OutputT (StackT mark f d) a)
-> Local r (StackT mark f d m) a
liftLocal local f x =
StackT $ \s -> do
StackTOut (Pair s1 a) <- local f $ fmap (StackTOut . bimap1 pure) $ unStackT x s
return $ Pair (unwrap s1) a
instance {-# OVERLAPPING #-}
( Monad m, MonadIdentity mark, IsStack f
) => MonadStack mark f d (StackT mark f d m)
where
push
:: Proxy f
-> mark d
-> StackT mark f d m ()
push _ d = StackT $ \s ->
return (Pair (stackPush (unwrap d) s) ())
pop
:: Proxy f
-> StackT mark f d m (mark (Maybe d))
pop _ = StackT $ \s ->
case stackPop s of
Nothing ->
return $ Pair s $ pure Nothing
Just (a,as) ->
return $ Pair as $ pure (Just a)
instance {-# OVERLAPPABLE #-}
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadStack mark f d m, IsStack f
) => MonadStack mark f d (StackT mark1 f1 d1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadState mark s m
) => MonadState mark s (StackT mark1 f d1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadReadOnly mark r m
) => MonadReadOnly mark r (StackT mark1 f d m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadWriteOnly mark w m, Monoid w
) => MonadWriteOnly mark w (StackT mark1 f d m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadExcept mark e m
) => MonadExcept mark e (StackT mark1 f d m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadPrompt mark p m
) => MonadPrompt mark p (StackT mark1 f d m)
instance
( Monad m, MonadIdentity mark1, MonadIdentity mark
, MonadHalt mark m
) => MonadHalt mark (StackT mark1 f d m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadAppendOnly mark w m, Monoid w
) => MonadAppendOnly mark w (StackT mark1 f d m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadWriteOnce mark w m
) => MonadWriteOnce mark w (StackT mark1 f d m)