{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.FX.Monad.Trans.AppendOnlyT (
AppendOnlyT(..)
, runAppendOnlyT
, Context(..)
, InputT(..)
, OutputT(..)
) where
import Data.Typeable (Typeable, typeOf)
import Control.Monad (ap)
import Control.FX.EqIn
import Control.FX.Functor
import Control.FX.Monad
import Control.FX.Monad.Trans.Class
newtype AppendOnlyT
(mark :: * -> *)
(w :: *)
(m :: * -> *)
(a :: *)
= AppendOnlyT
{ unAppendOnlyT :: w -> m (Pair w a)
} deriving (Typeable)
instance
( Typeable w, Typeable m, Typeable a, Typeable mark
) => Show (AppendOnlyT mark w m a)
where
show
:: AppendOnlyT mark w m a
-> String
show = show . typeOf
instance
( Monad m, MonadIdentity mark, Monoid w
) => Functor (AppendOnlyT mark w m)
where
fmap
:: (a -> b)
-> AppendOnlyT mark w m a
-> AppendOnlyT mark w m b
fmap f x =
x >>= (return . f)
instance
( Monad m, MonadIdentity mark, Monoid w
) => Applicative (AppendOnlyT mark w m)
where
pure
:: a
-> AppendOnlyT mark w m a
pure = return
(<*>)
:: AppendOnlyT mark w m (a -> b)
-> AppendOnlyT mark w m a
-> AppendOnlyT mark w m b
(<*>) = ap
instance
( Monad m, MonadIdentity mark, Monoid w
) => Monad (AppendOnlyT mark w m)
where
return
:: a
-> AppendOnlyT mark w m a
return x =
AppendOnlyT $ \_ ->
return $ Pair mempty x
(>>=)
:: AppendOnlyT mark w m a
-> (a -> AppendOnlyT mark w m b)
-> AppendOnlyT mark w m b
(AppendOnlyT x) >>= f =
AppendOnlyT $ \w1 -> do
Pair w2 a <- x w1
Pair w3 b <- unAppendOnlyT (f a) (w1 <> w2)
return $ Pair (w2 <> w3) b
instance
( MonadIdentity mark, Monoid w
) => MonadTrans (AppendOnlyT mark w)
where
lift
:: ( Monad m )
=> m a
-> AppendOnlyT mark w m a
lift x = AppendOnlyT $ \_ ->
fmap (\a -> Pair mempty a) x
instance
( MonadIdentity mark, Monoid w
) => MonadFunctor (AppendOnlyT mark w)
where
hoist
:: ( Monad m, Monad n )
=> (forall u. m u -> n u)
-> AppendOnlyT mark w m a
-> AppendOnlyT mark w n a
hoist f (AppendOnlyT x) =
AppendOnlyT $ \w -> do
a <- f $ fmap slot2 (x w)
return $ Pair mempty a
instance
( EqIn m, MonadIdentity mark, Eq w
) => EqIn (AppendOnlyT mark w m)
where
newtype Context (AppendOnlyT mark w m)
= AppendOnlyTCtx
{ unAppendOnlyTCtx :: (mark w, Context m)
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (AppendOnlyT mark w m)
-> AppendOnlyT mark w m a
-> AppendOnlyT mark w m a
-> Bool
eqIn (AppendOnlyTCtx (w,h)) (AppendOnlyT x) (AppendOnlyT y) =
eqIn h (x $ unwrap w) (y $ unwrap w)
deriving instance
( Eq (mark w), Eq (Context m)
) => Eq (Context (AppendOnlyT mark w m))
deriving instance
( Show (mark w), Show (Context m)
) => Show (Context (AppendOnlyT mark w m))
instance
( MonadIdentity mark, Monoid w
) => RunMonadTrans (AppendOnlyT mark w)
where
newtype InputT (AppendOnlyT mark w)
= AppendOnlyTIn
{ unAppendOnlyTIn :: mark ()
} deriving (Typeable)
newtype OutputT (AppendOnlyT mark w) a
= AppendOnlyTOut
{ unAppendOnlyTOut :: Pair (mark w) a
} deriving (Typeable)
runT
:: ( Monad m )
=> InputT (AppendOnlyT mark w)
-> AppendOnlyT mark w m a
-> m (OutputT (AppendOnlyT mark w) a)
runT _ (AppendOnlyT x) = do
Pair w a <- x mempty
return $ AppendOnlyTOut $ Pair (pure w) a
runAppendOnlyT
:: ( Monad m, MonadIdentity mark, Monoid w )
=> AppendOnlyT mark w m a
-> m (Pair (mark w) a)
runAppendOnlyT =
fmap unAppendOnlyTOut . runT (AppendOnlyTIn $ pure ())
deriving instance
( Eq (mark ())
) => Eq (InputT (AppendOnlyT mark w))
deriving instance
( Show (mark ())
) => Show (InputT (AppendOnlyT mark w))
deriving instance
( Eq (mark w), Eq a
) => Eq (OutputT (AppendOnlyT mark w) a)
deriving instance
( Show (mark w), Show a
) => Show (OutputT (AppendOnlyT mark w) a)
instance
( MonadIdentity mark, Monoid w
) => LiftCatch (AppendOnlyT mark w)
where
liftCatch
:: ( Monad m )
=> Catch e m (OutputT (AppendOnlyT mark w) a)
-> Catch e (AppendOnlyT mark w m) a
liftCatch catch x h = AppendOnlyT $ \w ->
fmap (bimap1 unwrap . unAppendOnlyTOut) $ catch
(fmap (AppendOnlyTOut . bimap1 pure) $ unAppendOnlyT x w)
(\e -> fmap (AppendOnlyTOut . bimap1 pure) $ unAppendOnlyT (h e) w)
instance
( MonadIdentity mark, Monoid w
) => LiftDraft (AppendOnlyT mark w)
where
liftDraft
:: ( Monad m )
=> Draft w1 m (OutputT (AppendOnlyT mark w) a)
-> Draft w1 (AppendOnlyT mark w m) a
liftDraft draft x =
AppendOnlyT $ \w -> do
Pair w_ (AppendOnlyTOut (Pair w1 a)) <-
draft $ fmap (AppendOnlyTOut . bimap1 pure) $ unAppendOnlyT x w
return $ Pair (unwrap w1) (Pair w_ a)
instance
( MonadIdentity mark, Monoid w
) => LiftLocal (AppendOnlyT mark w)
where
liftLocal
:: ( Monad m )
=> Local r m (OutputT (AppendOnlyT mark w) a)
-> Local r (AppendOnlyT mark w m) a
liftLocal local f x =
AppendOnlyT $ \w1 -> do
AppendOnlyTOut (Pair w2 a) <-
local f $ fmap (AppendOnlyTOut . bimap1 pure) $ unAppendOnlyT x w1
return $ Pair (unwrap w2) a
instance {-# OVERLAPPING #-}
( Monad m, MonadIdentity mark, Monoid w
) => MonadAppendOnly mark w (AppendOnlyT mark w m)
where
look
:: AppendOnlyT mark w m (mark w)
look = AppendOnlyT $ \w ->
return (Pair mempty (pure w))
jot
:: mark w
-> AppendOnlyT mark w m ()
jot w = AppendOnlyT $ \_ ->
return $ Pair (unwrap w) ()
instance {-# OVERLAPPABLE #-}
( Monad m, MonadIdentity mark, MonadIdentity mark1, Monoid w, Monoid w1
, MonadAppendOnly mark w m
) => MonadAppendOnly mark w (AppendOnlyT mark1 w1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1, Monoid w, Monoid w1
, MonadWriteOnce mark w m
) => MonadWriteOnce mark w (AppendOnlyT mark1 w1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1, Monoid w
, MonadState mark s m
) => MonadState mark s (AppendOnlyT mark1 w m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1, Monoid w
, MonadReadOnly mark r m
) => MonadReadOnly mark r (AppendOnlyT mark1 w m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1
, MonadWriteOnly mark w m, Monoid w, Monoid w1
) => MonadWriteOnly mark w (AppendOnlyT mark1 w1 m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1, Monoid w
, MonadExcept mark e m
) => MonadExcept mark e (AppendOnlyT mark1 w m)
instance
( Monad m, MonadIdentity mark, MonadIdentity mark1, Monoid w
, MonadPrompt mark p m
) => MonadPrompt mark p (AppendOnlyT mark1 w m)
instance
( Monad m, MonadIdentity mark1, MonadIdentity mark, Monoid w
, MonadHalt mark m
) => MonadHalt mark (AppendOnlyT mark1 w m)