{-# LANGUAGE GADTs #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Control.FX.Monad.Trans.ComposeT (
ComposableT(..)
, ComposeT(..)
, Context(..)
, InputT(..)
, OutputT(..)
) where
import Data.Typeable (Typeable)
import Control.Monad (ap)
import Control.FX.EqIn
import Control.FX.Functor
import Control.FX.Monad
import Control.FX.Monad.Trans.Class
import Control.FX.Monad.Trans.IdentityT
import Control.FX.Monad.Trans.ExceptT
import Control.FX.Monad.Trans.WriteOnlyT
import Control.FX.Monad.Trans.StateT
import Control.FX.Monad.Trans.ReadOnlyT
import Control.FX.Monad.Trans.HaltT
import Control.FX.Monad.Trans.AppendOnlyT
import Control.FX.Monad.Trans.WriteOnceT
class
( MonadTrans t1
) => ComposableT t1
where
data
ComposeT
(t1 :: (* -> *) -> * -> *)
(t2 :: (* -> *) -> * -> *)
(m :: * -> *)
(a :: *)
toComposeT
:: t1 (t2 m) a
-> ComposeT t1 t2 m a
unComposeT
:: ComposeT t1 t2 m a
-> t1 (t2 m) a
instance
ComposableT IdentityT
where
newtype (ComposeT IdentityT t2 m a) =
ComposeT_IdentityT
{ unComposeT_IdentityT :: IdentityT (t2 m) a
} deriving (Typeable)
toComposeT = ComposeT_IdentityT
unComposeT = unComposeT_IdentityT
instance
( MonadIdentity mark
) => ComposableT (HaltT mark)
where
newtype (ComposeT (HaltT mark) t2 m a) =
ComposeT_HaltT
{ unComposeT_HaltT :: HaltT mark (t2 m) a
} deriving (Typeable)
toComposeT = ComposeT_HaltT
unComposeT = unComposeT_HaltT
instance
( MonadIdentity mark
) => ComposableT (StateT mark s)
where
newtype (ComposeT (StateT mark s) t2 m a) =
ComposeT_StateT
{ unComposeT_StateT :: StateT mark s (t2 m) a
} deriving (Typeable)
toComposeT = ComposeT_StateT
unComposeT = unComposeT_StateT
instance
( MonadIdentity mark
) => ComposableT (ReadOnlyT mark r)
where
newtype (ComposeT (ReadOnlyT mark r) t2 m a) =
ComposeT_ReadOnlyT
{ unComposeT_ReadOnlyT :: ReadOnlyT mark r (t2 m) a
} deriving (Typeable)
toComposeT = ComposeT_ReadOnlyT
unComposeT = unComposeT_ReadOnlyT
instance
( MonadIdentity mark, Monoid w
) => ComposableT (WriteOnlyT mark w)
where
newtype (ComposeT (WriteOnlyT mark w) t2 m a) =
ComposeT_WriteOnlyT
{ unComposeT_WriteOnlyT :: WriteOnlyT mark w (t2 m) a
} deriving (Typeable)
toComposeT = ComposeT_WriteOnlyT
unComposeT = unComposeT_WriteOnlyT
instance
( MonadIdentity mark
) => ComposableT (WriteOnceT mark w)
where
newtype (ComposeT (WriteOnceT mark w) t2 m a) =
ComposeT_WriteOnceT
{ unComposeT_WriteOnceT :: WriteOnceT mark w (t2 m) a
} deriving (Typeable)
toComposeT = ComposeT_WriteOnceT
unComposeT = unComposeT_WriteOnceT
instance
( MonadIdentity mark, Monoid w
) => ComposableT (AppendOnlyT mark w)
where
newtype (ComposeT (AppendOnlyT mark w) t2 m a) =
ComposeT_AppendOnlyT
{ unComposeT_AppendOnlyT :: AppendOnlyT mark w (t2 m) a
} deriving (Typeable)
toComposeT = ComposeT_AppendOnlyT
unComposeT = unComposeT_AppendOnlyT
instance
( MonadIdentity mark
) => ComposableT (ExceptT mark e)
where
newtype (ComposeT (ExceptT mark e) t2 m a) =
ComposeT_ExceptT
{ unComposeT_ExceptT :: ExceptT mark e (t2 m) a
} deriving (Typeable)
toComposeT = ComposeT_ExceptT
unComposeT = unComposeT_ExceptT
instance
( Show (t1 (t2 m) a), ComposableT t1
) => Show (ComposeT t1 t2 m a)
where
show = show . unComposeT
instance
( Monad m, MonadTrans t1, MonadTrans t2, ComposableT t1
) => Functor (ComposeT t1 t2 m)
where
fmap
:: (a -> b)
-> ComposeT t1 t2 m a
-> ComposeT t1 t2 m b
fmap f = toComposeT . fmap f . unComposeT
instance
( Monad m, MonadTrans t1, MonadTrans t2, ComposableT t1
) => Applicative (ComposeT t1 t2 m)
where
pure
:: a
-> ComposeT t1 t2 m a
pure = return
(<*>)
:: ComposeT t1 t2 m (a -> b)
-> ComposeT t1 t2 m a
-> ComposeT t1 t2 m b
(<*>) = ap
instance
( Monad m, MonadTrans t1, MonadTrans t2, ComposableT t1
) => Monad (ComposeT t1 t2 m)
where
return
:: a
-> ComposeT t1 t2 m a
return = toComposeT . return
(>>=)
:: ComposeT t1 t2 m a
-> (a -> ComposeT t1 t2 m b)
-> ComposeT t1 t2 m b
x >>= f =
toComposeT ((unComposeT x) >>= (unComposeT . f))
instance
( MonadIdentity m, MonadTrans t1, MonadTrans t2, Eq a
, MonadIdentity (t2 m), MonadIdentity (t1 (t2 m))
, ComposableT t1
) => Eq (ComposeT t1 t2 m a)
where
(==)
:: ComposeT t1 t2 m a
-> ComposeT t1 t2 m a
-> Bool
x == y = (==)
(unwrap $ unComposeT x)
(unwrap $ unComposeT y)
instance
( MonadIdentity m, MonadTrans t1, MonadTrans t2, Semigroup a
, MonadIdentity (t2 m) , MonadIdentity (t1 (t2 m))
, ComposableT t1
) => Semigroup (ComposeT t1 t2 m a)
where
(<>)
:: ComposeT t1 t2 m a
-> ComposeT t1 t2 m a
-> ComposeT t1 t2 m a
a <> b = toComposeT $
(unComposeT a) <> (unComposeT b)
instance
( MonadIdentity m, MonadTrans t1, MonadTrans t2, Monoid a
, MonadIdentity (t2 m) , MonadIdentity (t1 (t2 m))
, ComposableT t1
) => Monoid (ComposeT t1 t2 m a)
where
mempty
:: ComposeT t1 t2 m a
mempty = toComposeT mempty
instance
( MonadTrans t1, MonadTrans t2, ComposableT t1
) => MonadTrans (ComposeT t1 t2)
where
lift
:: ( Monad m )
=> m a
-> ComposeT t1 t2 m a
lift = toComposeT . lift . lift
instance
( MonadFunctor t1, MonadFunctor t2, ComposableT t1
) => MonadFunctor (ComposeT t1 t2)
where
hoist
:: ( Monad m, Monad n )
=> (forall u. m u -> n u)
-> ComposeT t1 t2 m a
-> ComposeT t1 t2 n a
hoist f = toComposeT . hoist (hoist f) . unComposeT
instance
( EqIn (t1 (t2 m)), ComposableT t1
) => EqIn (ComposeT t1 t2 m)
where
newtype Context (ComposeT t1 t2 m)
= ComposeTCtx
{ unComposeTCtx :: Context (t1 (t2 m))
} deriving (Typeable)
eqIn
:: (Eq a)
=> Context (ComposeT t1 t2 m)
-> ComposeT t1 t2 m a
-> ComposeT t1 t2 m a
-> Bool
eqIn (ComposeTCtx h) x y =
eqIn h (unComposeT x) (unComposeT y)
deriving instance
( Eq (Context (t1 (t2 m)))
) => Eq (Context (ComposeT t1 t2 m))
deriving instance
( Show (Context (t1 (t2 m)))
) => Show (Context (ComposeT t1 t2 m))
instance
( RunMonadTrans t1, RunMonadTrans t2, ComposableT t1
) => RunMonadTrans (ComposeT t1 t2)
where
newtype InputT (ComposeT t1 t2)
= ComposeTIn
{ unComposeTIn :: (InputT t1, InputT t2)
} deriving (Typeable)
newtype OutputT (ComposeT t1 t2) a
= ComposeTOut
{ unComposeTOut :: Compose (OutputT t2) (OutputT t1) a
} deriving (Typeable)
runT
:: ( Monad m )
=> InputT (ComposeT t1 t2)
-> ComposeT t1 t2 m a
-> m (OutputT (ComposeT t1 t2) a)
runT (ComposeTIn (z1,z2)) =
fmap (ComposeTOut . Compose) . runT z2 . runT z1 . unComposeT
deriving instance
( Eq (InputT t1), Eq (InputT t2)
) => Eq (InputT (ComposeT t1 t2))
deriving instance
( Show (InputT t1), Show (InputT t2)
) => Show (InputT (ComposeT t1 t2))
deriving instance
( Eq (OutputT t2 (OutputT t1 a))
) => Eq (OutputT (ComposeT t1 t2) a)
deriving instance
( Show (OutputT t2 (OutputT t1 a))
) => Show (OutputT (ComposeT t1 t2) a)
instance
( LiftCatch t1, LiftCatch t2, ComposableT t1
) => LiftCatch (ComposeT t1 t2)
where
liftCatch
:: forall e a m
. ( Monad m )
=> Catch e m (OutputT (ComposeT t1 t2) a)
-> Catch e (ComposeT t1 t2 m) a
liftCatch catch x h = do
let
catch' :: Catch e m (OutputT t2 (OutputT t1 a))
catch' x' h' = fmap (unCompose . unComposeTOut) $
catch (fmap (ComposeTOut . Compose) x') (fmap (ComposeTOut . Compose) . h')
toComposeT $ liftCatch (liftCatch catch') (unComposeT x) (unComposeT . h)
instance
( LiftDraft t1, LiftDraft t2, ComposableT t1
) => LiftDraft (ComposeT t1 t2)
where
liftDraft
:: forall w m a
. ( Monad m, Monoid w )
=> Draft w m (OutputT (ComposeT t1 t2) a)
-> Draft w (ComposeT t1 t2 m) a
liftDraft draft x = do
let
draft' :: Draft w m (OutputT t2 (OutputT t1 a))
draft' y = fmap (fmap (unCompose . unComposeTOut)) $
draft (fmap (ComposeTOut . Compose) y)
toComposeT $ liftDraft (liftDraft draft') (unComposeT x)
instance
( LiftLocal t1, LiftLocal t2, ComposableT t1
) => LiftLocal (ComposeT t1 t2)
where
liftLocal
:: forall r m a
. ( Monad m )
=> Local r m (OutputT (ComposeT t1 t2) a)
-> Local r (ComposeT t1 t2 m) a
liftLocal local f x = do
let
local' :: Local r m (OutputT t2 (OutputT t1 a))
local' g y = fmap (unCompose . unComposeTOut) $
local g (fmap (ComposeTOut . Compose) y)
toComposeT $ liftLocal (liftLocal local') f $ unComposeT x
instance
( MonadIdentity m, MonadTrans t1, MonadTrans t2, ComposableT t1
, forall x. (MonadIdentity x) => MonadIdentity (t1 x)
, forall x. (MonadIdentity x) => MonadIdentity (t2 x)
) => MonadIdentity (ComposeT t1 t2 m)
where
unwrap
:: ComposeT t1 t2 m a
-> a
unwrap = unwrap . unComposeT
instance {-# OVERLAPS #-}
( Monad m, MonadTrans t2, MonadIdentity mark
) => MonadExcept mark e (ComposeT (ExceptT mark e) t2 m)
where
throw
:: mark e
-> ComposeT (ExceptT mark e) t2 m a
throw = toComposeT . throw
catch
:: ComposeT (ExceptT mark e) t2 m a
-> (mark e -> ComposeT (ExceptT mark e) t2 m a)
-> ComposeT (ExceptT mark e) t2 m a
catch x h = toComposeT $ catch (unComposeT x) (unComposeT . h)
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t1, MonadTrans t2, ComposableT t1
, MonadIdentity mark, LiftCatch t1
, forall x. (Monad x) => MonadExcept mark e (t2 x)
) => MonadExcept mark e (ComposeT t1 t2 m)
where
throw
:: mark e
-> ComposeT t1 t2 m a
throw = toComposeT . lift . throw
catch
:: ComposeT t1 t2 m a
-> (mark e -> ComposeT t1 t2 m a)
-> ComposeT t1 t2 m a
catch x h = toComposeT $
liftCatch catch (unComposeT x) (unComposeT . h)
instance {-# OVERLAPS #-}
( Monad m, MonadTrans t2, Monoid w, MonadIdentity mark
) => MonadWriteOnly mark w (ComposeT (WriteOnlyT mark w) t2 m)
where
draft
:: ComposeT (WriteOnlyT mark w) t2 m a
-> ComposeT (WriteOnlyT mark w) t2 m (Pair (mark w) a)
draft = toComposeT . draft . unComposeT
tell
:: mark w
-> ComposeT (WriteOnlyT mark w) t2 m ()
tell = toComposeT . tell
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t1, MonadTrans t2, Monoid w, ComposableT t1
, LiftDraft t1, MonadIdentity mark
, forall x. (Monad x) => MonadWriteOnly mark w (t2 x)
) => MonadWriteOnly mark w (ComposeT t1 t2 m)
where
draft
:: ComposeT t1 t2 m a
-> ComposeT t1 t2 m (Pair (mark w) a)
draft = toComposeT . liftDraft draft . unComposeT
tell
:: mark w
-> ComposeT t1 t2 m ()
tell = toComposeT . lift . tell
instance {-# OVERLAPS #-}
( Monad m, MonadTrans t2, MonadIdentity mark
) => MonadState mark s (ComposeT (StateT mark s) t2 m)
where
get
:: ComposeT (StateT mark s) t2 m (mark s)
get = toComposeT get
put
:: mark s -> ComposeT (StateT mark s) t2 m ()
put = toComposeT . put
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t1, MonadTrans t2, MonadIdentity mark, ComposableT t1
, forall x. (Monad x) => MonadState mark s (t2 x)
) => MonadState mark s (ComposeT t1 t2 m)
where
get
:: ComposeT t1 t2 m (mark s)
get = toComposeT $ lift get
put
:: mark s -> ComposeT t1 t2 m ()
put = toComposeT . lift . put
instance {-# OVERLAPS #-}
( Monad m, MonadTrans t2, MonadIdentity mark
) => MonadReadOnly mark r (ComposeT (ReadOnlyT mark r) t2 m)
where
ask
:: ComposeT (ReadOnlyT mark r) t2 m (mark r)
ask = toComposeT ask
local
:: (mark r -> mark r)
-> ComposeT (ReadOnlyT mark r) t2 m a
-> ComposeT (ReadOnlyT mark r) t2 m a
local f = toComposeT . local f . unComposeT
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t1, MonadTrans t2, ComposableT t1
, LiftLocal t1, MonadIdentity mark
, forall x. (Monad x) => MonadReadOnly mark r (t2 x)
) => MonadReadOnly mark r (ComposeT t1 t2 m)
where
ask
:: ComposeT t1 t2 m (mark r)
ask = toComposeT $ lift ask
local
:: (mark r -> mark r)
-> ComposeT t1 t2 m a
-> ComposeT t1 t2 m a
local f = toComposeT . liftLocal local f . unComposeT
instance {-# OVERLAPS #-}
( Monad m, MonadTrans t2, MonadIdentity mark
) => MonadHalt mark (ComposeT (HaltT mark) t2 m)
where
halt
:: mark ()
-> ComposeT (HaltT mark) t2 m a
halt = toComposeT . halt
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t1, MonadTrans t2, ComposableT t1
, LiftLocal t1, MonadIdentity mark
, forall x. (Monad x) => MonadHalt mark (t2 x)
) => MonadHalt mark (ComposeT t1 t2 m)
where
halt
:: mark ()
-> ComposeT t1 t2 m a
halt = toComposeT . lift . halt
instance {-# OVERLAPS #-}
( Monad m, MonadTrans t2, Monoid w, MonadIdentity mark
) => MonadAppendOnly mark w (ComposeT (AppendOnlyT mark w) t2 m)
where
look
:: ComposeT (AppendOnlyT mark w) t2 m (mark w)
look = toComposeT look
jot
:: mark w
-> ComposeT (AppendOnlyT mark w) t2 m ()
jot = toComposeT . jot
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t1, MonadTrans t2, Monoid w, ComposableT t1
, LiftDraft t1, MonadIdentity mark
, forall x. (Monad x) => MonadAppendOnly mark w (t2 x)
) => MonadAppendOnly mark w (ComposeT t1 t2 m)
where
look
:: ComposeT t1 t2 m (mark w)
look = toComposeT $ lift look
jot
:: mark w
-> ComposeT t1 t2 m ()
jot = toComposeT . lift . jot
instance {-# OVERLAPS #-}
( Monad m, MonadTrans t2, MonadIdentity mark
) => MonadWriteOnce mark w (ComposeT (WriteOnceT mark w) t2 m)
where
press
:: ComposeT (WriteOnceT mark w) t2 m (Maybe (mark w))
press = toComposeT press
etch
:: mark w
-> ComposeT (WriteOnceT mark w) t2 m Bool
etch = toComposeT . etch
instance {-# OVERLAPPABLE #-}
( Monad m, MonadTrans t1, MonadTrans t2, ComposableT t1
, LiftDraft t1, MonadIdentity mark
, forall x. (Monad x) => MonadWriteOnce mark w (t2 x)
) => MonadWriteOnce mark w (ComposeT t1 t2 m)
where
press
:: ComposeT t1 t2 m (Maybe (mark w))
press = toComposeT $ lift press
etch
:: mark w
-> ComposeT t1 t2 m Bool
etch = toComposeT . lift . etch