module Prologue.Control.Monad.Trans (module Prologue.Control.Monad.Trans, module X) where import Prelude import Control.Monad.Trans.Class as X (MonadTrans, lift) import Control.Monad.Primitive (PrimState) import Data.Kind (Constraint) -- === Type families === -- type family MonadTranses (ts :: [(* -> *) -> * -> *]) :: Constraint where MonadTranses '[] = () MonadTranses (t ': ts) = (MonadTrans t, MonadTranses ts) type MonadTransInvariants t m = (Monad m, Monad (t m), MonadTrans t) type PrimMonadTransInvariants t m = (MonadTransInvariants t m, PrimState m ~ PrimState (t m)) -- === Lifting === -- {-# WARNING lift2 "You should not use `lift2` in production code. Use monad transformer stack instead. If you really need it in a very specific use case, use `_lift2_` instead." #-} lift2, _lift2_ :: (Monad (t1 m), Monad m, MonadTranses '[t1,t2]) => m a -> t2 (t1 m) a lift2 = _lift2_ ; {-# INLINE lift2 #-} _lift2_ = lift . lift ; {-# INLINE _lift2_ #-} {-# WARNING lift3 "You should not use `lift3` in production code. Use monad transformer stack instead. If you really need it in a very specific use case, use `_lift3_` instead." #-} lift3, _lift3_ :: (Monad (t2 (t1 m)), Monad (t1 m), Monad m, MonadTranses '[t1,t2,t3]) => m a -> t3 (t2 (t1 m)) a lift3 = _lift3_ ; {-# INLINE lift3 #-} _lift3_ = lift . lift2 ; {-# INLINE _lift3_ #-} {-# WARNING lift4 "You should not use `lift4` in production code. Use monad transformer stack instead. If you really need it in a very specific use case, use `_lift4_` instead." #-} lift4, _lift4_ :: (Monad (t3 (t2 (t1 m))), Monad (t2 (t1 m)), Monad (t1 m), Monad m, MonadTranses '[t1,t2,t3,t4]) => m a -> t4 (t3 (t2 (t1 m))) a lift4 = _lift4_ ; {-# INLINE lift4 #-} _lift4_ = lift . lift3 ; {-# INLINE _lift4_ #-} {-# WARNING lift5 "You should not use `lift5` in production code. Use monad transformer stack instead. If you really need it in a very specific use case, use `_lift5_` instead." #-} lift5, _lift5_ :: (Monad (t4 (t3 (t2 (t1 m)))), Monad (t3 (t2 (t1 m))), Monad (t2 (t1 m)), Monad (t1 m), Monad m, MonadTranses '[t1,t2,t3,t4,t5]) => m a -> t5 (t4 (t3 (t2 (t1 m)))) a lift5 = _lift5_ ; {-# INLINE lift5 #-} _lift5_ = lift . lift4 ; {-# INLINE _lift5_ #-}