{-# LANGUAGE DerivingVia, FlexibleInstances, FunctionalDependencies, GeneralizedNewtypeDeriving, StandaloneDeriving, TypeFamilies, Rank2Types, UndecidableInstances #-}

module Control.Monad.Trans.Control.Identity (

-- * MonadTransControlIdentity
  MonadTransControlIdentity (..)
{- | 'MonadTransControlIdentity' instances can easily be created for
  monad transformers, because of the superclass 'MonadTransControl':

@
newtype ExampleT = ...
  deriving ('Monad', 'Control.Monad.Trans.Class.MonadTrans')

instance 'MonadTransControl' ExampleT where
  ...

instance 'MonadTransControlIdentity' ExampleT where
  'liftWithIdentity' f = 'liftWith' $ \\ runT -> f runT
@
-}

-- * MonadBaseControlIdentity
-- | Regarding the 'IO' base monad this can be seen as an alternative,
-- but equivalent, way to implement 'MonadUnliftIO'.
, MonadBaseControlIdentity (..)
{- | 'MonadBaseControlIdentity' instances can be created just as
  easily for monad transformers:

@
instance 'MonadBaseControlIdentity' b m => 'MonadBaseControlIdentity' b (ExampleT m) where
  'liftBaseWithIdentity' = 'defaultLiftBaseWithIdentity'
@
  -}
, defaultLiftBaseWithIdentity

) where

import Control.Monad.Base
import Control.Monad.ST.Lazy as L
import Control.Monad.ST.Strict as S
import Control.Monad.STM
import Control.Monad.Trans.Control
import Control.Monad.Trans.Identity
import Control.Monad.Trans.Reader
import Data.Functor.Identity

{- | The 'MonadTransControlIdentity' type class is a stronger version of
  'MonadTransControl':

  'MonadTransControl' instances are aware of the monadic state of the
  transformer and allow to save and restore this state.
  'MonadTransControlIdentity' instances on the other hand exist only for
  exactly those transformers, that don't have any monadic state.

  So for any instance of this class this should hold:

  @forall a. 'StT' t a ~ a@

  This can't be given as a constraint to the class due to limitations
  regarding the @TypeFamilies@ extension.
-}
class MonadTransControl t => MonadTransControlIdentity t where
  liftWithIdentity :: Monad m => ((forall x. t m x -> m x) -> m a) -> t m a

instance MonadTransControlIdentity IdentityT where
  liftWithIdentity :: forall (m :: * -> *) a.
Monad m =>
((forall x. IdentityT m x -> m x) -> m a) -> IdentityT m a
liftWithIdentity (forall x. IdentityT m x -> m x) -> m a
f = (Run IdentityT -> m a) -> IdentityT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTransControl t, Monad m) =>
(Run t -> m a) -> t m a
liftWith ((Run IdentityT -> m a) -> IdentityT m a)
-> (Run IdentityT -> m a) -> IdentityT m a
forall a b. (a -> b) -> a -> b
$ \ Run IdentityT
runT -> (forall x. IdentityT m x -> m x) -> m a
f forall x. IdentityT m x -> m x
Run IdentityT
runT

instance MonadTransControlIdentity (ReaderT r) where
  liftWithIdentity :: forall (m :: * -> *) a.
Monad m =>
((forall x. ReaderT r m x -> m x) -> m a) -> ReaderT r m a
liftWithIdentity (forall x. ReaderT r m x -> m x) -> m a
f = (Run (ReaderT r) -> m a) -> ReaderT r m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTransControl t, Monad m) =>
(Run t -> m a) -> t m a
liftWith ((Run (ReaderT r) -> m a) -> ReaderT r m a)
-> (Run (ReaderT r) -> m a) -> ReaderT r m a
forall a b. (a -> b) -> a -> b
$ \ Run (ReaderT r)
runT -> (forall x. ReaderT r m x -> m x) -> m a
f forall x. ReaderT r m x -> m x
Run (ReaderT r)
runT

{- | The 'MonadBaseControlIdentity' type class is a stronger version of
  'MonadBaseControl'.

  Just like 'MonadTransControlIdentity' instances of
  'MonadBaseControlIdentity' hold no monadic state:

  @forall a. 'StM' m a ~ a@
-}
class MonadBaseControl b m => MonadBaseControlIdentity b m | m -> b where
  liftBaseWithIdentity :: ((forall x. m x -> b x) -> b a) -> m a

defaultLiftBaseWithIdentity :: (MonadBaseControlIdentity b m, MonadTransControlIdentity t)
                            => ((forall x. t m x -> b x) -> b a)
                            -> t m a
defaultLiftBaseWithIdentity :: forall (b :: * -> *) (m :: * -> *) (t :: (* -> *) -> * -> *) a.
(MonadBaseControlIdentity b m, MonadTransControlIdentity t) =>
((forall x. t m x -> b x) -> b a) -> t m a
defaultLiftBaseWithIdentity (forall x. t m x -> b x) -> b a
inner = ((forall x. t m x -> m x) -> m a) -> t m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTransControlIdentity t, Monad m) =>
((forall x. t m x -> m x) -> m a) -> t m a
liftWithIdentity (((forall x. t m x -> m x) -> m a) -> t m a)
-> ((forall x. t m x -> m x) -> m a) -> t m a
forall a b. (a -> b) -> a -> b
$ \ forall x. t m x -> m x
runId ->
  ((forall x. m x -> b x) -> b a) -> m a
forall (b :: * -> *) (m :: * -> *) a.
MonadBaseControlIdentity b m =>
((forall x. m x -> b x) -> b a) -> m a
liftBaseWithIdentity (((forall x. m x -> b x) -> b a) -> m a)
-> ((forall x. m x -> b x) -> b a) -> m a
forall a b. (a -> b) -> a -> b
$ \ forall x. m x -> b x
runIdInBase ->
    (forall x. t m x -> b x) -> b a
inner ((forall x. t m x -> b x) -> b a)
-> (forall x. t m x -> b x) -> b a
forall a b. (a -> b) -> a -> b
$ m x -> b x
forall x. m x -> b x
runIdInBase (m x -> b x) -> (t m x -> m x) -> t m x -> b x
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t m x -> m x
forall x. t m x -> m x
runId

instance MonadBaseControlIdentity b m => MonadBaseControlIdentity b (IdentityT m) where
  liftBaseWithIdentity :: forall a.
((forall x. IdentityT m x -> b x) -> b a) -> IdentityT m a
liftBaseWithIdentity = ((forall x. IdentityT m x -> b x) -> b a) -> IdentityT m a
forall (b :: * -> *) (m :: * -> *) (t :: (* -> *) -> * -> *) a.
(MonadBaseControlIdentity b m, MonadTransControlIdentity t) =>
((forall x. t m x -> b x) -> b a) -> t m a
defaultLiftBaseWithIdentity

instance MonadBaseControlIdentity b m => MonadBaseControlIdentity b (ReaderT r m) where
  liftBaseWithIdentity :: forall a.
((forall x. ReaderT r m x -> b x) -> b a) -> ReaderT r m a
liftBaseWithIdentity = ((forall x. ReaderT r m x -> b x) -> b a) -> ReaderT r m a
forall (b :: * -> *) (m :: * -> *) (t :: (* -> *) -> * -> *) a.
(MonadBaseControlIdentity b m, MonadTransControlIdentity t) =>
((forall x. t m x -> b x) -> b a) -> t m a
defaultLiftBaseWithIdentity

deriving via Base IO instance MonadBaseControlIdentity IO IO
deriving via Base Maybe instance MonadBaseControlIdentity Maybe Maybe
deriving via Base (Either e) instance MonadBaseControlIdentity (Either e) (Either e)
deriving via Base [] instance MonadBaseControlIdentity [] []
deriving via Base ((->) r) instance MonadBaseControlIdentity ((->) r) ((->) r)
deriving via Base Identity instance MonadBaseControlIdentity Identity Identity
deriving via Base STM instance MonadBaseControlIdentity STM STM
deriving via Base (S.ST s) instance MonadBaseControlIdentity (S.ST s) (S.ST s)
deriving via Base (L.ST s) instance MonadBaseControlIdentity (L.ST s) (L.ST s)

newtype Base m a = MkBase { forall (m :: * -> *) a. Base m a -> m a
getBase :: m a }
  deriving newtype ((forall a b. (a -> b) -> Base m a -> Base m b)
-> (forall a b. a -> Base m b -> Base m a) -> Functor (Base m)
forall a b. a -> Base m b -> Base m a
forall a b. (a -> b) -> Base m a -> Base m b
forall (m :: * -> *) a b. Functor m => a -> Base m b -> Base m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> Base m a -> Base m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Base m b -> Base m a
$c<$ :: forall (m :: * -> *) a b. Functor m => a -> Base m b -> Base m a
fmap :: forall a b. (a -> b) -> Base m a -> Base m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> Base m a -> Base m b
Functor, Functor (Base m)
Functor (Base m)
-> (forall a. a -> Base m a)
-> (forall a b. Base m (a -> b) -> Base m a -> Base m b)
-> (forall a b c.
    (a -> b -> c) -> Base m a -> Base m b -> Base m c)
-> (forall a b. Base m a -> Base m b -> Base m b)
-> (forall a b. Base m a -> Base m b -> Base m a)
-> Applicative (Base m)
forall a. a -> Base m a
forall a b. Base m a -> Base m b -> Base m a
forall a b. Base m a -> Base m b -> Base m b
forall a b. Base m (a -> b) -> Base m a -> Base m b
forall a b c. (a -> b -> c) -> Base m a -> Base m b -> Base m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
forall {m :: * -> *}. Applicative m => Functor (Base m)
forall (m :: * -> *) a. Applicative m => a -> Base m a
forall (m :: * -> *) a b.
Applicative m =>
Base m a -> Base m b -> Base m a
forall (m :: * -> *) a b.
Applicative m =>
Base m a -> Base m b -> Base m b
forall (m :: * -> *) a b.
Applicative m =>
Base m (a -> b) -> Base m a -> Base m b
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c) -> Base m a -> Base m b -> Base m c
<* :: forall a b. Base m a -> Base m b -> Base m a
$c<* :: forall (m :: * -> *) a b.
Applicative m =>
Base m a -> Base m b -> Base m a
*> :: forall a b. Base m a -> Base m b -> Base m b
$c*> :: forall (m :: * -> *) a b.
Applicative m =>
Base m a -> Base m b -> Base m b
liftA2 :: forall a b c. (a -> b -> c) -> Base m a -> Base m b -> Base m c
$cliftA2 :: forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c) -> Base m a -> Base m b -> Base m c
<*> :: forall a b. Base m (a -> b) -> Base m a -> Base m b
$c<*> :: forall (m :: * -> *) a b.
Applicative m =>
Base m (a -> b) -> Base m a -> Base m b
pure :: forall a. a -> Base m a
$cpure :: forall (m :: * -> *) a. Applicative m => a -> Base m a
Applicative, Applicative (Base m)
Applicative (Base m)
-> (forall a b. Base m a -> (a -> Base m b) -> Base m b)
-> (forall a b. Base m a -> Base m b -> Base m b)
-> (forall a. a -> Base m a)
-> Monad (Base m)
forall a. a -> Base m a
forall a b. Base m a -> Base m b -> Base m b
forall a b. Base m a -> (a -> Base m b) -> Base m b
forall {m :: * -> *}. Monad m => Applicative (Base m)
forall (m :: * -> *) a. Monad m => a -> Base m a
forall (m :: * -> *) a b.
Monad m =>
Base m a -> Base m b -> Base m b
forall (m :: * -> *) a b.
Monad m =>
Base m a -> (a -> Base m b) -> Base m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: forall a. a -> Base m a
$creturn :: forall (m :: * -> *) a. Monad m => a -> Base m a
>> :: forall a b. Base m a -> Base m b -> Base m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
Base m a -> Base m b -> Base m b
>>= :: forall a b. Base m a -> (a -> Base m b) -> Base m b
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
Base m a -> (a -> Base m b) -> Base m b
Monad)

instance Monad m => MonadBase m (Base m) where
  liftBase :: forall α. m α -> Base m α
liftBase = m α -> Base m α
forall (m :: * -> *) a. m a -> Base m a
MkBase

instance Monad m => MonadBaseControl m (Base m) where
  type StM (Base m) a = a
  liftBaseWith :: forall a. (RunInBase (Base m) m -> m a) -> Base m a
liftBaseWith RunInBase (Base m) m -> m a
inner = m a -> Base m a
forall (m :: * -> *) a. m a -> Base m a
MkBase (m a -> Base m a) -> m a -> Base m a
forall a b. (a -> b) -> a -> b
$ RunInBase (Base m) m -> m a
inner RunInBase (Base m) m
forall (m :: * -> *) a. Base m a -> m a
getBase
  restoreM :: forall a. StM (Base m) a -> Base m a
restoreM = StM (Base m) a -> Base m a
forall (m :: * -> *) a. Monad m => a -> m a
return

instance Monad m => MonadBaseControlIdentity m (Base m) where
  liftBaseWithIdentity :: forall a. ((forall x. Base m x -> m x) -> m a) -> Base m a
liftBaseWithIdentity (forall x. Base m x -> m x) -> m a
inner = m a -> Base m a
forall (m :: * -> *) a. m a -> Base m a
MkBase (m a -> Base m a) -> m a -> Base m a
forall a b. (a -> b) -> a -> b
$ (forall x. Base m x -> m x) -> m a
inner forall x. Base m x -> m x
forall (m :: * -> *) a. Base m a -> m a
getBase