{-# LANGUAGE UndecidableInstances #-}
module LittleRIO
( RIO (..)
, mapRIO
, liftRIO
, unliftRIO
, runRIO
, SomeRef (..)
, readSomeRef
, writeSomeRef
, modifySomeRef
, newSomeRef
, HasStateRef (..)
, HasWriteRef (..)
, ResourceMap
, HasResourceMap (..)
, withResourceMap
)
where
import Control.Applicative (liftA2)
import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)
import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.IO.Unlift (MonadUnliftIO (..), UnliftIO, askUnliftIO)
import Control.Monad.Primitive (PrimMonad (..))
import Control.Monad.Reader (MonadReader (..), ReaderT (..), asks)
import Control.Monad.State (MonadState (..))
import Control.Monad.Trans.Resource (InternalState, MonadResource (..), ResourceT, runResourceT, withInternalState)
import Control.Monad.Trans.Resource.Internal (unResourceT)
import Control.Monad.Writer (MonadWriter (..))
import Data.IORef (IORef, newIORef, readIORef, writeIORef)
import Lens.Micro (Lens')
import Lens.Micro.Extras (view)
import LittleLogger (LogActionWrapperM (..), MonadLogger)
newtype RIO env a = RIO {forall env a. RIO env a -> ReaderT env IO a
unRIO :: ReaderT env IO a}
deriving newtype
( 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
<$ :: forall a b. a -> RIO env b -> RIO env a
$c<$ :: forall env a b. a -> RIO env b -> RIO env a
fmap :: forall a b. (a -> b) -> RIO env a -> RIO env b
$cfmap :: forall env a b. (a -> b) -> RIO env a -> RIO env b
Functor
, 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
<* :: forall a b. RIO env a -> RIO env b -> RIO env a
$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 b
$c*> :: forall env a b. RIO env a -> RIO env b -> RIO env b
liftA2 :: forall a b c. (a -> b -> c) -> RIO env a -> RIO env b -> RIO env c
$cliftA2 :: forall env a b c.
(a -> b -> c) -> RIO env a -> RIO env b -> RIO env c
<*> :: forall a b. RIO env (a -> b) -> RIO env a -> RIO env b
$c<*> :: forall env a b. RIO env (a -> b) -> RIO env a -> RIO env b
pure :: forall a. a -> RIO env a
$cpure :: forall env a. a -> RIO env a
Applicative
, 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
return :: forall a. a -> RIO env a
$creturn :: forall env a. a -> RIO env a
>> :: 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 b
>>= :: forall a b. RIO env a -> (a -> RIO env b) -> RIO env b
$c>>= :: forall env a b. RIO env a -> (a -> RIO env b) -> RIO env b
Monad
, MonadReader 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
liftIO :: forall a. IO a -> RIO env a
$cliftIO :: forall env a. IO a -> RIO env a
MonadIO
, forall env. Monad (RIO env)
forall e a. Exception e => e -> RIO env a
forall env e a. Exception e => e -> RIO env a
forall (m :: * -> *).
Monad m -> (forall e a. Exception e => e -> m a) -> MonadThrow m
throwM :: forall e a. Exception e => e -> RIO env a
$cthrowM :: forall env e a. Exception e => e -> RIO env a
MonadThrow
, forall env. Monad (RIO env)
forall a. String -> RIO env a
forall env a. String -> RIO env a
forall (m :: * -> *).
Monad m -> (forall a. String -> m a) -> MonadFail m
fail :: forall a. String -> RIO env a
$cfail :: forall env a. String -> RIO env a
MonadFail
, forall env. MonadThrow (RIO env)
forall e a.
Exception e =>
RIO env a -> (e -> RIO env a) -> RIO env a
forall env e a.
Exception e =>
RIO env a -> (e -> RIO env a) -> RIO env a
forall (m :: * -> *).
MonadThrow m
-> (forall e a. Exception e => m a -> (e -> m a) -> m a)
-> MonadCatch m
catch :: forall e a.
Exception e =>
RIO env a -> (e -> RIO env a) -> RIO env a
$ccatch :: forall env e a.
Exception e =>
RIO env a -> (e -> RIO env a) -> RIO env a
MonadCatch
, forall env. MonadCatch (RIO env)
forall b.
((forall a. RIO env a -> RIO env a) -> RIO env b) -> RIO env b
forall env b.
((forall a. RIO env a -> RIO env a) -> RIO env b) -> RIO env b
forall a b c.
RIO env a
-> (a -> ExitCase b -> RIO env c)
-> (a -> RIO env b)
-> RIO env (b, c)
forall env a b c.
RIO env a
-> (a -> ExitCase b -> RIO env c)
-> (a -> RIO env b)
-> RIO env (b, c)
forall (m :: * -> *).
MonadCatch m
-> (forall b. ((forall a. m a -> m a) -> m b) -> m b)
-> (forall b. ((forall a. m a -> m a) -> m b) -> m b)
-> (forall a b c.
m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> m (b, c))
-> MonadMask m
generalBracket :: forall a b c.
RIO env a
-> (a -> ExitCase b -> RIO env c)
-> (a -> RIO env b)
-> RIO env (b, c)
$cgeneralBracket :: forall env a b c.
RIO env a
-> (a -> ExitCase b -> RIO env c)
-> (a -> RIO env b)
-> RIO env (b, c)
uninterruptibleMask :: forall b.
((forall a. RIO env a -> RIO env a) -> RIO env b) -> RIO env b
$cuninterruptibleMask :: forall env b.
((forall a. RIO env a -> RIO env a) -> RIO env b) -> RIO env b
mask :: forall b.
((forall a. RIO env a -> RIO env a) -> RIO env b) -> RIO env b
$cmask :: forall env b.
((forall a. RIO env a -> RIO env a) -> RIO env b) -> RIO env b
MonadMask
, forall env. MonadIO (RIO env)
forall b. ((forall a. RIO env a -> IO a) -> IO b) -> RIO env b
forall env b. ((forall a. RIO env a -> IO a) -> IO b) -> RIO env b
forall (m :: * -> *).
MonadIO m
-> (forall b. ((forall a. m a -> IO a) -> IO b) -> m b)
-> MonadUnliftIO m
withRunInIO :: forall b. ((forall a. RIO env a -> IO a) -> IO b) -> RIO env b
$cwithRunInIO :: forall env b. ((forall a. RIO env a -> IO a) -> IO b) -> RIO env b
MonadUnliftIO
)
deriving (forall msg.
ToLogStr msg =>
Loc -> LogSource -> LogLevel -> msg -> RIO env ()
forall {env}. HasLogAction env => Monad (RIO env)
forall env msg.
(HasLogAction env, ToLogStr msg) =>
Loc -> LogSource -> LogLevel -> msg -> RIO env ()
forall (m :: * -> *).
Monad m
-> (forall msg.
ToLogStr msg =>
Loc -> LogSource -> LogLevel -> msg -> m ())
-> MonadLogger m
monadLoggerLog :: forall msg.
ToLogStr msg =>
Loc -> LogSource -> LogLevel -> msg -> RIO env ()
$cmonadLoggerLog :: forall env msg.
(HasLogAction env, ToLogStr msg) =>
Loc -> LogSource -> LogLevel -> msg -> RIO env ()
MonadLogger) via LogActionWrapperM env (RIO env)
instance Semigroup a => Semigroup (RIO env a) where
<> :: RIO env a -> RIO env a -> RIO env a
(<>) = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Semigroup a => a -> a -> a
(<>)
instance Monoid a => Monoid (RIO env a) where
mempty :: RIO env a
mempty = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Monoid a => a
mempty
mappend :: RIO env a -> RIO env a -> RIO env a
mappend = forall a. Semigroup a => a -> a -> a
(<>)
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 = forall env a. ReaderT env IO a -> RIO env a
RIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> b -> a
const forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive
mapRIO :: (env -> env') -> RIO env' a -> RIO env a
mapRIO :: forall env env' a. (env -> env') -> RIO env' a -> RIO env a
mapRIO env -> env'
f RIO env' a
m = do
env
env <- forall r (m :: * -> *). MonadReader r m => m r
ask
let env' :: env'
env' = env -> env'
f env
env
forall (m :: * -> *) env a. MonadIO m => env -> RIO env a -> m a
runRIO env'
env' RIO env' a
m
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
m = do
env
env <- forall r (m :: * -> *). MonadReader r m => m r
ask
forall (m :: * -> *) env a. MonadIO m => env -> RIO env a -> m a
runRIO env
env RIO env a
m
unliftRIO :: MonadIO m => env -> m (UnliftIO (RIO env))
unliftRIO :: forall (m :: * -> *) env.
MonadIO m =>
env -> m (UnliftIO (RIO env))
unliftRIO env
env = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall (m :: * -> *) env a. MonadIO m => env -> RIO env a -> m a
runRIO env
env forall (m :: * -> *). MonadUnliftIO m => m (UnliftIO m)
askUnliftIO)
runRIO :: MonadIO m => env -> RIO env a -> m a
runRIO :: forall (m :: * -> *) env a. MonadIO m => env -> RIO env a -> m a
runRIO env
r RIO env a
m = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (forall env a. RIO env a -> ReaderT env IO a
unRIO RIO env a
m) env
r)
data SomeRef a = SomeRef !(IO a) !(a -> IO ())
readSomeRef :: MonadIO m => SomeRef a -> m a
readSomeRef :: forall (m :: * -> *) a. MonadIO m => SomeRef a -> m a
readSomeRef (SomeRef IO a
x a -> IO ()
_) = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO a
x
writeSomeRef :: MonadIO m => SomeRef a -> a -> m ()
writeSomeRef :: forall (m :: * -> *) a. MonadIO m => SomeRef a -> a -> m ()
writeSomeRef (SomeRef IO a
_ a -> IO ()
x) = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> IO ()
x
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 = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a
read' forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> IO ()
write 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 = forall a. IO a -> (a -> IO ()) -> SomeRef a
SomeRef (forall a. IORef a -> IO a
readIORef IORef a
ref) (forall a. IORef a -> a -> IO ()
writeIORef IORef a
ref)
newSomeRef :: MonadIO m => a -> m (SomeRef a)
newSomeRef :: forall (m :: * -> *) a. MonadIO m => a -> m (SomeRef a)
newSomeRef = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. IORef a -> SomeRef a
ioRefToSomeRef forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> IO (IORef a)
newIORef
class HasStateRef st env | env -> st where
stateRefL :: Lens' env (SomeRef st)
instance HasStateRef a (SomeRef a) where
stateRefL :: Lens' (SomeRef a) (SomeRef a)
stateRefL = forall a. a -> a
id
getStateRef :: (HasStateRef st env, MonadReader env m, MonadIO m) => m st
getStateRef :: forall st env (m :: * -> *).
(HasStateRef st env, MonadReader env m, MonadIO m) =>
m st
getStateRef = do
SomeRef st
ref <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (forall a s. Getting a s a -> s -> a
view forall st env. HasStateRef st env => Lens' env (SomeRef st)
stateRefL)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall (m :: * -> *) a. MonadIO m => SomeRef a -> m a
readSomeRef SomeRef st
ref)
putStateRef :: (HasStateRef st env, MonadReader env m, MonadIO m) => st -> m ()
putStateRef :: forall st env (m :: * -> *).
(HasStateRef st env, MonadReader env m, MonadIO m) =>
st -> m ()
putStateRef st
st = do
SomeRef st
ref <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (forall a s. Getting a s a -> s -> a
view forall st env. HasStateRef st env => Lens' env (SomeRef st)
stateRefL)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall (m :: * -> *) a. MonadIO m => SomeRef a -> a -> m ()
writeSomeRef SomeRef st
ref st
st)
modifyStateRef :: (HasStateRef st env, MonadReader env m, MonadIO m) => (st -> st) -> m ()
modifyStateRef :: forall st env (m :: * -> *).
(HasStateRef st env, MonadReader env m, MonadIO m) =>
(st -> st) -> m ()
modifyStateRef st -> st
f = do
SomeRef st
ref <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (forall a s. Getting a s a -> s -> a
view forall st env. HasStateRef st env => Lens' env (SomeRef st)
stateRefL)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall (m :: * -> *) a. MonadIO m => SomeRef a -> (a -> a) -> m ()
modifySomeRef SomeRef st
ref st -> st
f)
instance HasStateRef st env => MonadState st (RIO env) where
get :: RIO env st
get = forall st env (m :: * -> *).
(HasStateRef st env, MonadReader env m, MonadIO m) =>
m st
getStateRef
put :: st -> RIO env ()
put = forall st env (m :: * -> *).
(HasStateRef st env, MonadReader env m, MonadIO m) =>
st -> m ()
putStateRef
class HasWriteRef w env | env -> w where
writeRefL :: Lens' env (SomeRef w)
instance HasWriteRef a (SomeRef a) where
writeRefL :: Lens' (SomeRef a) (SomeRef a)
writeRefL = forall a. a -> a
id
tellWriteRef :: (HasWriteRef w env, MonadReader env m, MonadIO m, Semigroup w) => w -> m ()
tellWriteRef :: forall w env (m :: * -> *).
(HasWriteRef w env, MonadReader env m, MonadIO m, Semigroup w) =>
w -> m ()
tellWriteRef w
value = do
SomeRef w
ref <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (forall a s. Getting a s a -> s -> a
view forall w env. HasWriteRef w env => Lens' env (SomeRef w)
writeRefL)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall (m :: * -> *) a. MonadIO m => SomeRef a -> (a -> a) -> m ()
modifySomeRef SomeRef w
ref (forall a. Semigroup a => a -> a -> a
<> w
value))
listenWriteRef :: (HasWriteRef w env, MonadReader env m, MonadIO m) => m a -> m (a, w)
listenWriteRef :: forall w env (m :: * -> *) a.
(HasWriteRef w env, MonadReader env m, MonadIO m) =>
m a -> m (a, w)
listenWriteRef m a
action = do
w
w1 <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (forall a s. Getting a s a -> s -> a
view forall w env. HasWriteRef w env => Lens' env (SomeRef w)
writeRefL) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. MonadIO m => SomeRef a -> m a
readSomeRef
a
a <- m a
action
w
w2 <- do
SomeRef w
refEnv <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (forall a s. Getting a s a -> s -> a
view forall w env. HasWriteRef w env => Lens' env (SomeRef w)
writeRefL)
w
v <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall (m :: * -> *) a. MonadIO m => SomeRef a -> m a
readSomeRef SomeRef w
refEnv)
()
_ <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall (m :: * -> *) a. MonadIO m => SomeRef a -> a -> m ()
writeSomeRef SomeRef w
refEnv w
w1)
forall (m :: * -> *) a. Monad m => a -> m a
return w
v
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a, w
w2)
passWriteRef :: (HasWriteRef w env, MonadReader env m, MonadIO m) => m (a, w -> w) -> m a
passWriteRef :: forall w env (m :: * -> *) a.
(HasWriteRef w env, MonadReader env m, MonadIO m) =>
m (a, w -> w) -> m a
passWriteRef m (a, w -> w)
action = do
(a
a, w -> w
transF) <- m (a, w -> w)
action
SomeRef w
ref <- forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (forall a s. Getting a s a -> s -> a
view forall w env. HasWriteRef w env => Lens' env (SomeRef w)
writeRefL)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (forall (m :: * -> *) a. MonadIO m => SomeRef a -> (a -> a) -> m ()
modifySomeRef SomeRef w
ref w -> w
transF)
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
instance (Monoid w, HasWriteRef w env) => MonadWriter w (RIO env) where
tell :: w -> RIO env ()
tell = forall w env (m :: * -> *).
(HasWriteRef w env, MonadReader env m, MonadIO m, Semigroup w) =>
w -> m ()
tellWriteRef
listen :: forall a. RIO env a -> RIO env (a, w)
listen = forall w env (m :: * -> *) a.
(HasWriteRef w env, MonadReader env m, MonadIO m) =>
m a -> m (a, w)
listenWriteRef
pass :: forall a. RIO env (a, w -> w) -> RIO env a
pass = forall w env (m :: * -> *) a.
(HasWriteRef w env, MonadReader env m, MonadIO m) =>
m (a, w -> w) -> m a
passWriteRef
type ResourceMap = InternalState
withResourceMap :: MonadUnliftIO m => (ResourceMap -> m a) -> m a
withResourceMap :: forall (m :: * -> *) a.
MonadUnliftIO m =>
(ResourceMap -> m a) -> m a
withResourceMap ResourceMap -> m a
inner = forall (m :: * -> *) a. MonadUnliftIO m => ResourceT m a -> m a
runResourceT (forall (m :: * -> *) a. (ResourceMap -> m a) -> ResourceT m a
withInternalState ResourceMap -> m a
inner)
class HasResourceMap env where
resourceMapL :: Lens' env ResourceMap
instance HasResourceMap ResourceMap where
resourceMapL :: Lens' ResourceMap ResourceMap
resourceMapL = forall a. a -> a
id
resourceRIO :: HasResourceMap env => ResourceT IO a -> RIO env a
resourceRIO :: forall env a. HasResourceMap env => ResourceT IO a -> RIO env a
resourceRIO ResourceT IO a
m = forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (forall a s. Getting a s a -> s -> a
view forall env. HasResourceMap env => Lens' env ResourceMap
resourceMapL) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. ResourceT m a -> ResourceMap -> m a
unResourceT ResourceT IO a
m
instance HasResourceMap env => MonadResource (RIO env) where
liftResourceT :: forall a. ResourceT IO a -> RIO env a
liftResourceT = forall env a. HasResourceMap env => ResourceT IO a -> RIO env a
resourceRIO