    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE FunctionalDependencies #-}
    {-# LANGUAGE UndecidableInstances #-}
    module RIO.Prelude.RIO
      ( RIO (..)
      , runRIO
      , liftRIO
      , mapRIO
      -- SomeRef for Writer/State interfaces

      , SomeRef
      , HasStateRef (..)
      , HasWriteRef (..)
      , newSomeRef
      , newUnboxedSomeRef
      , readSomeRef
      , writeSomeRef
      , modifySomeRef
      ) where

    import GHC.Exts (RealWorld)

    import RIO.Prelude.Lens
    import RIO.Prelude.URef
    import RIO.Prelude.Reexports
    import Control.Monad.State (MonadState(..))
    import Control.Monad.Writer (MonadWriter(..))

    -- | The Reader+IO monad. This is different from a 'ReaderT' because:

    --

    -- * It's not a transformer, it hardcodes IO for simpler usage and

    -- error messages.

    --

    -- * Instances of typeclasses like 'MonadLogger' are implemented using

    -- classes defined on the environment, instead of using an

    -- underlying monad.

    newtype RIO env a = RIO { forall env a. RIO env a -> ReaderT env IO a
    unRIO :: ReaderT env IO a }
      deriving ((forall a b. (a -> b) -> RIO env a -> RIO env b)
    -> (forall a b. a -> RIO env b -> RIO env a) -> Functor (RIO env)
    forall a b. a -> RIO env b -> RIO env a
    forall a b. (a -> b) -> RIO env a -> RIO env b
    forall env a b. a -> RIO env b -> RIO env a
    forall env a b. (a -> b) -> RIO env a -> RIO env b
    forall (f :: * -> *).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall env a b. (a -> b) -> RIO env a -> RIO env b
    fmap :: forall a b. (a -> b) -> RIO env a -> RIO env b
    $c<$ :: forall env a b. a -> RIO env b -> RIO env a
    <$ :: forall a b. a -> RIO env b -> RIO env a
    Functor,Functor (RIO env)
    Functor (RIO env) =>
    (forall a. a -> RIO env a)
    -> (forall a b. RIO env (a -> b) -> RIO env a -> RIO env b)
    -> (forall a b c.
        (a -> b -> c) -> RIO env a -> RIO env b -> RIO env c)
    -> (forall a b. RIO env a -> RIO env b -> RIO env b)
    -> (forall a b. RIO env a -> RIO env b -> RIO env a)
    -> Applicative (RIO env)
    forall env. Functor (RIO env)
    forall a. a -> RIO env a
    forall env a. a -> RIO env a
    forall a b. RIO env a -> RIO env b -> RIO env a
    forall a b. RIO env a -> RIO env b -> RIO env b
    forall a b. RIO env (a -> b) -> RIO env a -> RIO env b
    forall env a b. RIO env a -> RIO env b -> RIO env a
    forall env a b. RIO env a -> RIO env b -> RIO env b
    forall env a b. RIO env (a -> b) -> RIO env a -> RIO env b
    forall a b c. (a -> b -> c) -> RIO env a -> RIO env b -> RIO env c
    forall env a b c.
    (a -> b -> c) -> RIO env a -> RIO env b -> RIO env 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
    $cpure :: forall env a. a -> RIO env a
    pure :: forall a. a -> RIO env a
    $c<*> :: forall env a b. RIO env (a -> b) -> RIO env a -> RIO env b
    <*> :: forall a b. RIO env (a -> b) -> RIO env a -> RIO env b
    $cliftA2 :: forall env a b c.
    (a -> b -> c) -> RIO env a -> RIO env b -> RIO env c
    liftA2 :: forall a b c. (a -> b -> c) -> RIO env a -> RIO env b -> RIO env c
    $c*> :: forall env a b. RIO env a -> RIO env b -> RIO env b
    *> :: forall a b. RIO env a -> RIO env b -> RIO env b
    $c<* :: forall env a b. RIO env a -> RIO env b -> RIO env a
    <* :: forall a b. RIO env a -> RIO env b -> RIO env a
    Applicative,Applicative (RIO env)
    Applicative (RIO env) =>
    (forall a b. RIO env a -> (a -> RIO env b) -> RIO env b)
    -> (forall a b. RIO env a -> RIO env b -> RIO env b)
    -> (forall a. a -> RIO env a)
    -> Monad (RIO env)
    forall env. Applicative (RIO env)
    forall a. a -> RIO env a
    forall env a. a -> RIO env a
    forall a b. RIO env a -> RIO env b -> RIO env b
    forall a b. RIO env a -> (a -> RIO env b) -> RIO env b
    forall env a b. RIO env a -> RIO env b -> RIO env b
    forall env a b. RIO env a -> (a -> RIO env b) -> RIO env 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
    $c>>= :: forall env a b. RIO env a -> (a -> RIO env b) -> RIO env b
    >>= :: forall a b. RIO env a -> (a -> RIO env b) -> RIO env b
    $c>> :: forall env a b. RIO env a -> RIO env b -> RIO env b
    >> :: forall a b. RIO env a -> RIO env b -> RIO env b
    $creturn :: forall env a. a -> RIO env a
    return :: forall a. a -> RIO env a
    Monad,Monad (RIO env)
    Monad (RIO env) =>
    (forall a. IO a -> RIO env a) -> MonadIO (RIO env)
    forall env. Monad (RIO env)
    forall a. IO a -> RIO env a
    forall env a. IO a -> RIO env a
    forall (m :: * -> *).
    Monad m =>
    (forall a. IO a -> m a) -> MonadIO m
    $cliftIO :: forall env a. IO a -> RIO env a
    liftIO :: forall a. IO a -> RIO env a
    MonadIO,MonadReader env,Monad (RIO env)
    Monad (RIO env) =>
    (forall e a. (HasCallStack, Exception e) => e -> RIO env a)
    -> MonadThrow (RIO env)
    forall env. Monad (RIO env)
    forall e a. (HasCallStack, Exception e) => e -> RIO env a
    forall env e a. (HasCallStack, Exception e) => e -> RIO env a
    forall (m :: * -> *).
    Monad m =>
    (forall e a. (HasCallStack, Exception e) => e -> m a)
    -> MonadThrow m
    $cthrowM :: forall env e a. (HasCallStack, Exception e) => e -> RIO env a
    throwM :: forall e a. (HasCallStack, Exception e) => e -> RIO env a
    MonadThrow)

    instance Semigroup a => Semigroup (RIO env a) where
      <> :: RIO env a -> RIO env a -> RIO env a
    (<>) = (a -> a -> a) -> RIO env a -> RIO env a -> RIO env a
    forall a b c. (a -> b -> c) -> RIO env a -> RIO env b -> RIO env c
    forall (f :: * -> *) a b c.
    Applicative f =>
    (a -> b -> c) -> f a -> f b -> f c
    liftA2 a -> a -> a
    forall a. Semigroup a => a -> a -> a
    (<>)
    instance Monoid a => Monoid (RIO env a) where
      mempty :: RIO env a
    mempty = a -> RIO env a
    forall a. a -> RIO env a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure a
    forall a. Monoid a => a
    mempty
      mappend :: RIO env a -> RIO env a -> RIO env a
    mappend = (a -> a -> a) -> RIO env a -> RIO env a -> RIO env a
    forall a b c. (a -> b -> c) -> RIO env a -> RIO env b -> RIO env c
    forall (f :: * -> *) a b c.
    Applicative f =>
    (a -> b -> c) -> f a -> f b -> f c
    liftA2 a -> a -> a
    forall a. Monoid a => a -> a -> a
    mappend

    -- | Using the environment run in IO the action that requires that environment.

    --

    -- @since 0.0.1.0

    runRIO :: MonadIO m => env -> RIO env a -> m a
    runRIO :: forall (m :: * -> *) env a. MonadIO m => env -> RIO env a -> m a
    runRIO env
    env (RIO (ReaderT env -> IO a
    f)) = IO a -> m a
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (env -> IO a
    f env
    env)

    -- | Abstract `RIO` to an arbitrary `MonadReader` instance, which can handle IO.

    --

    -- @since 0.0.1.0

    liftRIO :: (MonadIO m, MonadReader env m) => RIO env a -> m a
    liftRIO :: forall (m :: * -> *) env a.
    (MonadIO m, MonadReader env m) =>
    RIO env a -> m a
    liftRIO RIO env a
    rio = do
      env <- m env
    forall r (m :: * -> *). MonadReader r m => m r
    ask
      runRIO env rio

    -- | Lift one RIO env to another.

    --

    -- @since 0.1.13.0

    mapRIO :: (outer -> inner) -> RIO inner a -> RIO outer a
    mapRIO :: forall outer inner a.
    (outer -> inner) -> RIO inner a -> RIO outer a
    mapRIO outer -> inner
    f RIO inner a
    m = do
      outer <- RIO outer outer
    forall r (m :: * -> *). MonadReader r m => m r
    ask
      runRIO (f outer) m

    instance MonadUnliftIO (RIO env) where
      withRunInIO :: forall b. ((forall a. RIO env a -> IO a) -> IO b) -> RIO env b
    withRunInIO (forall a. RIO env a -> IO a) -> IO b
    inner = ReaderT env IO b -> RIO env b
    forall env a. ReaderT env IO a -> RIO env a
    RIO (ReaderT env IO b -> RIO env b) -> ReaderT env IO b -> RIO env b
    forall a b. (a -> b) -> a -> b
    $ ((forall a. ReaderT env IO a -> IO a) -> IO b) -> ReaderT env IO b
    forall b.
    ((forall a. ReaderT env IO a -> IO a) -> IO b) -> ReaderT env IO b
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. ReaderT env IO a -> IO a) -> IO b)
     -> ReaderT env IO b)
    -> ((forall a. ReaderT env IO a -> IO a) -> IO b)
    -> ReaderT env IO b
    forall a b. (a -> b) -> a -> b
    $ \forall a. ReaderT env IO a -> IO a
    run -> (forall a. RIO env a -> IO a) -> IO b
    inner (ReaderT env IO a -> IO a
    forall a. ReaderT env IO a -> IO a
    run (ReaderT env IO a -> IO a)
    -> (RIO env a -> ReaderT env IO a) -> RIO env a -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . RIO env a -> ReaderT env IO a
    forall env a. RIO env a -> ReaderT env IO a
    unRIO)
      {-# INLINE withRunInIO #-}

    instance PrimMonad (RIO env) where
        type PrimState (RIO env) = PrimState IO
        primitive :: forall a.
    (State# (PrimState (RIO env))
     -> (# State# (PrimState (RIO env)), a #))
    -> RIO env a
    primitive = ReaderT env IO a -> RIO env a
    forall env a. ReaderT env IO a -> RIO env a
    RIO (ReaderT env IO a -> RIO env a)
    -> ((State# RealWorld -> (# State# RealWorld, a #))
        -> ReaderT env IO a)
    -> (State# RealWorld -> (# State# RealWorld, a #))
    -> RIO env a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (env -> IO a) -> ReaderT env IO a
    forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
    ReaderT ((env -> IO a) -> ReaderT env IO a)
    -> ((State# RealWorld -> (# State# RealWorld, a #)) -> env -> IO a)
    -> (State# RealWorld -> (# State# RealWorld, a #))
    -> ReaderT env IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IO a -> env -> IO a
    forall a b. a -> b -> a
    const (IO a -> env -> IO a)
    -> ((State# RealWorld -> (# State# RealWorld, a #)) -> IO a)
    -> (State# RealWorld -> (# State# RealWorld, a #))
    -> env
    -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
    (State# (PrimState IO) -> (# State# (PrimState IO), a #)) -> IO a
    forall a.
    (State# (PrimState IO) -> (# State# (PrimState IO), a #)) -> IO a
    forall (m :: * -> *) a.
    PrimMonad m =>
    (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
    primitive

    -- | Abstraction over how to read from and write to a mutable reference

    --

    -- @since 0.1.4.0

    data SomeRef a
      = SomeRef !(IO a) !(a -> IO ())

    -- | Read from a SomeRef

    --

    -- @since 0.1.4.0

    readSomeRef :: MonadIO m => SomeRef a -> m a
    readSomeRef :: forall (m :: * -> *) a. MonadIO m => SomeRef a -> m a
    readSomeRef (SomeRef IO a
    x a -> IO ()
    _) = IO a -> m a
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO a
    x

    -- | Write to a SomeRef

    --

    -- @since 0.1.4.0

    writeSomeRef :: MonadIO m => SomeRef a -> a -> m ()
    writeSomeRef :: forall (m :: * -> *) a. MonadIO m => SomeRef a -> a -> m ()
    writeSomeRef (SomeRef IO a
    _ a -> IO ()
    x) = IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (a -> IO ()) -> a -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> IO ()
    x

    -- | Modify a SomeRef

    -- This function is subject to change due to the lack of atomic operations

    --

    -- @since 0.1.4.0

    modifySomeRef :: MonadIO m => SomeRef a -> (a -> a) -> m ()
    modifySomeRef :: forall (m :: * -> *) a. MonadIO m => SomeRef a -> (a -> a) -> m ()
    modifySomeRef (SomeRef IO a
    read' a -> IO ()
    write) a -> a
    f =
      IO () -> m ()
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO a
    read' IO a -> (a -> IO ()) -> IO ()
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= a -> IO ()
    write (a -> IO ()) -> (a -> a) -> a -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a
    f)

    ioRefToSomeRef :: IORef a -> SomeRef a
    ioRefToSomeRef :: forall a. IORef a -> SomeRef a
    ioRefToSomeRef IORef a
    ref =
      IO a -> (a -> IO ()) -> SomeRef a
    forall a. IO a -> (a -> IO ()) -> SomeRef a
    SomeRef (IORef a -> IO a
    forall (m :: * -> *) a. MonadIO m => IORef a -> m a
    readIORef IORef a
    ref)
              (IORef a -> (a -> a) -> IO ()
    forall (m :: * -> *) a. MonadIO m => IORef a -> (a -> a) -> m ()
    modifyIORef' IORef a
    ref ((a -> a) -> IO ()) -> (a -> a -> a) -> a -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a -> a
    forall a b. a -> b -> a
    const)

    uRefToSomeRef :: Unbox a => URef RealWorld a -> SomeRef a
    uRefToSomeRef :: forall a. Unbox a => URef RealWorld a -> SomeRef a
    uRefToSomeRef URef RealWorld a
    ref =
      IO a -> (a -> IO ()) -> SomeRef a
    forall a. IO a -> (a -> IO ()) -> SomeRef a
    SomeRef (URef (PrimState IO) a -> IO a
    forall (m :: * -> *) a.
    (PrimMonad m, Unbox a) =>
    URef (PrimState m) a -> m a
    readURef URef RealWorld a
    URef (PrimState IO) a
    ref) (URef (PrimState IO) a -> a -> IO ()
    forall (m :: * -> *) a.
    (PrimMonad m, Unbox a) =>
    URef (PrimState m) a -> a -> m ()
    writeURef URef RealWorld a
    URef (PrimState IO) a
    ref)

    -- | Environment values with stateful capabilities to SomeRef

    --

    -- @since 0.1.4.0

    class HasStateRef s env | env -> s where
      stateRefL :: Lens' env (SomeRef s)

    -- | Identity state reference where the SomeRef is the env

    --

    -- @since 0.1.4.0

    instance HasStateRef a (SomeRef a) where
      stateRefL :: Lens' (SomeRef a) (SomeRef a)
    stateRefL = (SomeRef a -> f (SomeRef a)) -> SomeRef a -> f (SomeRef a)
    forall a. a -> a
    id

    -- | Environment values with writing capabilities to SomeRef

    --

    -- @since 0.1.4.0

    class HasWriteRef w env | env -> w where
      writeRefL :: Lens' env (SomeRef w)

    -- | Identity write reference where the SomeRef is the env

    --

    -- @since 0.1.4.0

    instance HasWriteRef a (SomeRef a) where
      writeRefL :: Lens' (SomeRef a) (SomeRef a)
    writeRefL = (SomeRef a -> f (SomeRef a)) -> SomeRef a -> f (SomeRef a)
    forall a. a -> a
    id

    instance HasStateRef s env => MonadState s (RIO env) where
      get :: RIO env s
    get = do
        ref <- Getting (SomeRef s) env (SomeRef s) -> RIO env (SomeRef s)
    forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
    view Getting (SomeRef s) env (SomeRef s)
    forall s env. HasStateRef s env => Lens' env (SomeRef s)
    Lens' env (SomeRef s)
    stateRefL
        liftIO $ readSomeRef ref
      put :: s -> RIO env ()
    put s
    st = do
        ref <- Getting (SomeRef s) env (SomeRef s) -> RIO env (SomeRef s)
    forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
    view Getting (SomeRef s) env (SomeRef s)
    forall s env. HasStateRef s env => Lens' env (SomeRef s)
    Lens' env (SomeRef s)
    stateRefL
        liftIO $ writeSomeRef ref st

    instance (Monoid w, HasWriteRef w env) => MonadWriter w (RIO env) where
      tell :: w -> RIO env ()
    tell w
    value = do
        ref <- Getting (SomeRef w) env (SomeRef w) -> RIO env (SomeRef w)
    forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
    view Getting (SomeRef w) env (SomeRef w)
    forall w env. HasWriteRef w env => Lens' env (SomeRef w)
    Lens' env (SomeRef w)
    writeRefL
        liftIO $ modifySomeRef ref (`mappend` value)

      listen :: forall a. RIO env a -> RIO env (a, w)
    listen RIO env a
    action = do
        w1 <- Getting (SomeRef w) env (SomeRef w) -> RIO env (SomeRef w)
    forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
    view Getting (SomeRef w) env (SomeRef w)
    forall w env. HasWriteRef w env => Lens' env (SomeRef w)
    Lens' env (SomeRef w)
    writeRefL RIO env (SomeRef w) -> (SomeRef w -> RIO env w) -> RIO env w
    forall a b. RIO env a -> (a -> RIO env b) -> RIO env b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= IO w -> RIO env w
    forall a. IO a -> RIO env a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO w -> RIO env w)
    -> (SomeRef w -> IO w) -> SomeRef w -> RIO env w
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SomeRef w -> IO w
    forall (m :: * -> *) a. MonadIO m => SomeRef a -> m a
    readSomeRef
        a <- action
        w2 <- do
          refEnv <- view writeRefL
          v <- liftIO $ readSomeRef refEnv
          _ <- liftIO $ writeSomeRef refEnv w1
          return v
        return (a, w2)

      pass :: forall a. RIO env (a, w -> w) -> RIO env a
    pass RIO env (a, w -> w)
    action = do
        (a, transF) <- RIO env (a, w -> w)
    action
        ref <- view writeRefL
        liftIO $ modifySomeRef ref transF
        return a

    -- | create a new boxed SomeRef

    --

    -- @since 0.1.4.0

    newSomeRef :: MonadIO m => a -> m (SomeRef a)
    newSomeRef :: forall (m :: * -> *) a. MonadIO m => a -> m (SomeRef a)
    newSomeRef a
    a = do
      IORef a -> SomeRef a
    forall a. IORef a -> SomeRef a
    ioRefToSomeRef (IORef a -> SomeRef a) -> m (IORef a) -> m (SomeRef a)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> a -> m (IORef a)
    forall (m :: * -> *) a. MonadIO m => a -> m (IORef a)
    newIORef a
    a

    -- | create a new unboxed SomeRef

    --

    -- @since 0.1.4.0

    newUnboxedSomeRef :: (MonadIO m, Unbox a) => a -> m (SomeRef a)
    newUnboxedSomeRef :: forall (m :: * -> *) a. (MonadIO m, Unbox a) => a -> m (SomeRef a)
    newUnboxedSomeRef a
    a =
      URef RealWorld a -> SomeRef a
    forall a. Unbox a => URef RealWorld a -> SomeRef a
    uRefToSomeRef (URef RealWorld a -> SomeRef a)
    -> m (URef RealWorld a) -> m (SomeRef a)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>   IO (URef RealWorld a) -> m (URef RealWorld a)
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (a -> IO (URef (PrimState IO) a)
    forall (m :: * -> *) a.
    (PrimMonad m, Unbox a) =>
    a -> m (URef (PrimState m) a)
    newURef a
    a)