-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | An easy to use, performant extensible effects library. -- -- An easy to use, performant extensible effects library with seamless -- integration with the existing Haskell ecosystem. -- -- This is the "batteries-included" variant. See the -- effectful-core package if you need a more limited -- dependency footprint or want to browse documentation of core modules. @package effectful @version 2.2.1.0 -- | Lifted Control.Concurrent.Chan. module Effectful.Concurrent.Chan -- | Provide the ability to run Eff computations concurrently in -- multiple threads and communicate between them. -- -- Warning: unless you stick to high level functions from the -- withAsync family, the Concurrent effect makes it -- possible to escape the scope of any scoped effect operation. Consider -- the following: -- --
--   >>> import qualified Effectful.Reader.Static as R
--   
-- --
--   >>> printAsk msg = liftIO . putStrLn . (msg ++) . (": " ++) =<< R.ask
--   
-- --
--   >>> :{
--     runEff . R.runReader "GLOBAL" . runConcurrent $ do
--       a <- R.local (const "LOCAL") $ do
--         a <- async $ do
--           printAsk "child (first)"
--           threadDelay 20000
--           printAsk "child (second)"
--         threadDelay 10000
--         printAsk "parent (inside)"
--         pure a
--       printAsk "parent (outside)"
--       wait a
--   :}
--   child (first): LOCAL
--   parent (inside): LOCAL
--   parent (outside): GLOBAL
--   child (second): LOCAL
--   
-- -- Note that the asynchronous computation doesn't respect the scope of -- local, i.e. the child thread still behaves like it's inside the -- local block, even though the parent thread already got out of -- it. -- -- This is because the value provided by the Reader effect is -- thread local, i.e. each thread manages its own version of it. For the -- Reader it is the only reasonable behavior, it wouldn't be very -- useful if its "read only" value was affected by calls to local -- from its parent or child threads. -- -- However, the cut isn't so clear if it comes to effects that provide -- access to a mutable state. That's why statically dispatched -- State and Writer effects come in two flavors, local -- and shared: -- --
--   >>> import qualified Effectful.State.Static.Local as SL
--   
--   >>> :{
--     runEff . SL.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SL.modify (++ "!")
--   :}
--   "Hi"
--   
-- --
--   >>> import qualified Effectful.State.Static.Shared as SS
--   
--   >>> :{
--     runEff . SS.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SS.modify (++ "!")
--   :}
--   "Hi!!!"
--   
-- -- In the first example state updates made concurrently are not reflected -- in the parent thread because the value is thread local, but in the -- second example they are, because the value is shared. data Concurrent :: Effect -- | Run the Concurrent effect. runConcurrent :: IOE :> es => Eff (Concurrent : es) a -> Eff es a -- | Chan is an abstract type representing an unbounded FIFO -- channel. data Chan a -- | Lifted newChan. newChan :: Concurrent :> es => Eff es (Chan a) -- | Lifted writeChan. writeChan :: Concurrent :> es => Chan a -> a -> Eff es () -- | Lifted readChan. readChan :: Concurrent :> es => Chan a -> Eff es a -- | Lifted dupChan. dupChan :: Concurrent :> es => Chan a -> Eff es (Chan a) -- | Lifted getChanContents. getChanContents :: Concurrent :> es => Chan a -> Eff es [a] -- | Lifted writeList2Chan. writeList2Chan :: Concurrent :> es => Chan a -> [a] -> Eff es () -- | Lifted Control.Concurrent.Async. module Effectful.Concurrent.Async -- | Provide the ability to run Eff computations concurrently in -- multiple threads and communicate between them. -- -- Warning: unless you stick to high level functions from the -- withAsync family, the Concurrent effect makes it -- possible to escape the scope of any scoped effect operation. Consider -- the following: -- --
--   >>> import qualified Effectful.Reader.Static as R
--   
-- --
--   >>> printAsk msg = liftIO . putStrLn . (msg ++) . (": " ++) =<< R.ask
--   
-- --
--   >>> :{
--     runEff . R.runReader "GLOBAL" . runConcurrent $ do
--       a <- R.local (const "LOCAL") $ do
--         a <- async $ do
--           printAsk "child (first)"
--           threadDelay 20000
--           printAsk "child (second)"
--         threadDelay 10000
--         printAsk "parent (inside)"
--         pure a
--       printAsk "parent (outside)"
--       wait a
--   :}
--   child (first): LOCAL
--   parent (inside): LOCAL
--   parent (outside): GLOBAL
--   child (second): LOCAL
--   
-- -- Note that the asynchronous computation doesn't respect the scope of -- local, i.e. the child thread still behaves like it's inside the -- local block, even though the parent thread already got out of -- it. -- -- This is because the value provided by the Reader effect is -- thread local, i.e. each thread manages its own version of it. For the -- Reader it is the only reasonable behavior, it wouldn't be very -- useful if its "read only" value was affected by calls to local -- from its parent or child threads. -- -- However, the cut isn't so clear if it comes to effects that provide -- access to a mutable state. That's why statically dispatched -- State and Writer effects come in two flavors, local -- and shared: -- --
--   >>> import qualified Effectful.State.Static.Local as SL
--   
--   >>> :{
--     runEff . SL.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SL.modify (++ "!")
--   :}
--   "Hi"
--   
-- --
--   >>> import qualified Effectful.State.Static.Shared as SS
--   
--   >>> :{
--     runEff . SS.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SS.modify (++ "!")
--   :}
--   "Hi!!!"
--   
-- -- In the first example state updates made concurrently are not reflected -- in the parent thread because the value is thread local, but in the -- second example they are, because the value is shared. data Concurrent :: Effect -- | Run the Concurrent effect. runConcurrent :: IOE :> es => Eff (Concurrent : es) a -> Eff es a -- | An asynchronous action spawned by async or withAsync. -- Asynchronous actions are executed in a separate thread, and operations -- are provided for waiting for asynchronous actions to complete and -- obtaining their results (see e.g. wait). data Async a -- | Lifted withAsync. withAsync :: Concurrent :> es => Eff es a -> (Async a -> Eff es b) -> Eff es b -- | Lifted withAsyncBound. withAsyncBound :: Concurrent :> es => Eff es a -> (Async a -> Eff es b) -> Eff es b -- | Lifted withAsyncOn. withAsyncOn :: Concurrent :> es => Int -> Eff es a -> (Async a -> Eff es b) -> Eff es b -- | Lifted withAsyncWithUnmask. withAsyncWithUnmask :: Concurrent :> es => ((forall c. Eff es c -> Eff es c) -> Eff es a) -> (Async a -> Eff es b) -> Eff es b -- | Lifted withAsyncOnWithUnmask. withAsyncOnWithUnmask :: Concurrent :> es => Int -> ((forall c. Eff es c -> Eff es c) -> Eff es a) -> (Async a -> Eff es b) -> Eff es b -- | Lifted wait. wait :: Concurrent :> es => Async a -> Eff es a -- | Lifted poll. poll :: Concurrent :> es => Async a -> Eff es (Maybe (Either SomeException a)) -- | Lifted waitCatch. waitCatch :: Concurrent :> es => Async a -> Eff es (Either SomeException a) -- | Returns the ThreadId of the thread running the given -- Async. asyncThreadId :: Async a -> ThreadId -- | Lifted cancel. cancel :: Concurrent :> es => Async a -> Eff es () -- | Lifted uninterruptibleCancel. uninterruptibleCancel :: Concurrent :> es => Async a -> Eff es () -- | Lifted cancelWith. cancelWith :: (Exception e, Concurrent :> es) => Async a -> e -> Eff es () -- | The exception thrown by cancel to terminate a thread. data AsyncCancelled AsyncCancelled :: AsyncCancelled -- | Compare two Asyncs that may have different types by their -- ThreadId. compareAsyncs :: Async a -> Async b -> Ordering -- | Lifted race. race :: Concurrent :> es => Eff es a -> Eff es b -> Eff es (Either a b) -- | Lifted race_. race_ :: Concurrent :> es => Eff es a -> Eff es b -> Eff es () -- | Lifted concurrently. concurrently :: Concurrent :> es => Eff es a -> Eff es b -> Eff es (a, b) -- | Lifted concurrently_. concurrently_ :: Concurrent :> es => Eff es a -> Eff es b -> Eff es () -- | Lifted mapConcurrently. mapConcurrently :: (Traversable f, Concurrent :> es) => (a -> Eff es b) -> f a -> Eff es (f b) -- | Lifted forConcurrently. forConcurrently :: (Traversable f, Concurrent :> es) => f a -> (a -> Eff es b) -> Eff es (f b) -- | Lifted mapConcurrently_. mapConcurrently_ :: (Foldable f, Concurrent :> es) => (a -> Eff es b) -> f a -> Eff es () -- | Lifted forConcurrently_. forConcurrently_ :: (Foldable f, Concurrent :> es) => f a -> (a -> Eff es b) -> Eff es () -- | Lifted replicateConcurrently. replicateConcurrently :: Concurrent :> es => Int -> Eff es a -> Eff es [a] -- | Lifted replicateConcurrently_. replicateConcurrently_ :: Concurrent :> es => Int -> Eff es a -> Eff es () -- | Lifted Concurrently. newtype Concurrently es a Concurrently :: Eff es a -> Concurrently es a [runConcurrently] :: Concurrently es a -> Eff es a -- | Lifted Conc. data Conc :: [Effect] -> Type -> Type -- | Lifted conc. conc :: Eff es a -> Conc es a -- | Lifted runConc. runConc :: Concurrent :> es => Conc es a -> Eff es a -- | Things that can go wrong in the structure of a Conc. These are -- programmer errors. data ConcException EmptyWithNoAlternative :: ConcException -- | Lifted pooledMapConcurrentlyN. pooledMapConcurrentlyN :: (Concurrent :> es, Traversable t) => Int -> (a -> Eff es b) -> t a -> Eff es (t b) -- | Lifted pooledMapConcurrently. pooledMapConcurrently :: (Concurrent :> es, Traversable t) => (a -> Eff es b) -> t a -> Eff es (t b) -- | Lifted pooledMapConcurrentlyN. pooledMapConcurrentlyN_ :: (Concurrent :> es, Foldable f) => Int -> (a -> Eff es b) -> f a -> Eff es () -- | Lifted pooledMapConcurrently_. pooledMapConcurrently_ :: (Concurrent :> es, Foldable f) => (a -> Eff es b) -> f a -> Eff es () -- | Lifted pooledForConcurrentlyN. pooledForConcurrentlyN :: (Concurrent :> es, Traversable t) => Int -> t a -> (a -> Eff es b) -> Eff es (t b) -- | Lifted pooledForConcurrently. pooledForConcurrently :: (Concurrent :> es, Traversable t) => t a -> (a -> Eff es b) -> Eff es (t b) -- | Lifted pooledForConcurrentlyN. pooledForConcurrentlyN_ :: (Concurrent :> es, Foldable f) => Int -> f a -> (a -> Eff es b) -> Eff es () -- | Lifted pooledForConcurrently_. pooledForConcurrently_ :: (Concurrent :> es, Foldable f) => f a -> (a -> Eff es b) -> Eff es () -- | Lifted pooledReplicateConcurrentlyN. pooledReplicateConcurrentlyN :: Concurrent :> es => Int -> Int -> Eff es a -> Eff es [a] -- | Lifted pooledReplicateConcurrently. pooledReplicateConcurrently :: Concurrent :> es => Int -> Eff es a -> Eff es [a] -- | Lifted pooledReplicateConcurrentlyN_. pooledReplicateConcurrentlyN_ :: Concurrent :> es => Int -> Int -> Eff es a -> Eff es () -- | Lifted pooledReplicateConcurrently_. pooledReplicateConcurrently_ :: Concurrent :> es => Int -> Eff es a -> Eff es () -- | A version of wait that can be used inside an STM transaction. waitSTM :: Async a -> STM a -- | A version of poll that can be used inside an STM transaction. pollSTM :: Async a -> STM (Maybe (Either SomeException a)) -- | A version of waitCatch that can be used inside an STM -- transaction. waitCatchSTM :: Async a -> STM (Either SomeException a) -- | Lifted waitAny. waitAny :: Concurrent :> es => [Async a] -> Eff es (Async a, a) -- | Lifted waitAnyCatch. waitAnyCatch :: Concurrent :> es => [Async a] -> Eff es (Async a, Either SomeException a) -- | Lifted waitAnyCancel. waitAnyCancel :: Concurrent :> es => [Async a] -> Eff es (Async a, a) -- | Lifted waitAnyCatchCancel. waitAnyCatchCancel :: Concurrent :> es => [Async a] -> Eff es (Async a, Either SomeException a) -- | Lifted waitEither. waitEither :: Concurrent :> es => Async a -> Async b -> Eff es (Either a b) -- | Lifted waitEitherCatch. waitEitherCatch :: Concurrent :> es => Async a -> Async b -> Eff es (Either (Either SomeException a) (Either SomeException b)) -- | Lifted waitEitherCancel. waitEitherCancel :: Concurrent :> es => Async a -> Async b -> Eff es (Either a b) -- | Lifted waitEitherCatchCancel. waitEitherCatchCancel :: Concurrent :> es => Async a -> Async b -> Eff es (Either (Either SomeException a) (Either SomeException b)) -- | Lifted waitEither_. waitEither_ :: Concurrent :> es => Async a -> Async b -> Eff es () -- | Lifted waitBoth. waitBoth :: Concurrent :> es => Async a -> Async b -> Eff es (a, b) -- | A version of waitAny that can be used inside an STM -- transaction. waitAnySTM :: [Async a] -> STM (Async a, a) -- | A version of waitAnyCatch that can be used inside an STM -- transaction. waitAnyCatchSTM :: [Async a] -> STM (Async a, Either SomeException a) -- | A version of waitEither that can be used inside an STM -- transaction. waitEitherSTM :: Async a -> Async b -> STM (Either a b) -- | A version of waitEitherCatch that can be used inside an STM -- transaction. waitEitherCatchSTM :: Async a -> Async b -> STM (Either (Either SomeException a) (Either SomeException b)) -- | A version of waitEither_ that can be used inside an STM -- transaction. waitEitherSTM_ :: Async a -> Async b -> STM () -- | A version of waitBoth that can be used inside an STM -- transaction. waitBothSTM :: Async a -> Async b -> STM (a, b) -- | Lifted async. async :: Concurrent :> es => Eff es a -> Eff es (Async a) -- | Lifted asyncBound. asyncBound :: Concurrent :> es => Eff es a -> Eff es (Async a) -- | Lifted asyncOn. asyncOn :: Concurrent :> es => Int -> Eff es a -> Eff es (Async a) -- | Lifted asyncWithUnmask. asyncWithUnmask :: Concurrent :> es => ((forall b. Eff es b -> Eff es b) -> Eff es a) -> Eff es (Async a) -- | Lifted asyncOnWithUnmask. asyncOnWithUnmask :: Concurrent :> es => Int -> ((forall b. Eff es b -> Eff es b) -> Eff es a) -> Eff es (Async a) -- | Lifted link. link :: Concurrent :> es => Async a -> Eff es () -- | Lifted linkOnly. linkOnly :: Concurrent :> es => (SomeException -> Bool) -> Async a -> Eff es () -- | Lifted link2. link2 :: Concurrent :> es => Async a -> Async b -> Eff es () -- | Lifted link2Only. link2Only :: Concurrent :> es => (SomeException -> Bool) -> Async a -> Async b -> Eff es () data ExceptionInLinkedThread ExceptionInLinkedThread :: Async a -> SomeException -> ExceptionInLinkedThread instance GHC.Base.Functor (Effectful.Concurrent.Async.Conc es) instance GHC.Base.Functor (Effectful.Concurrent.Async.Concurrently es) instance (Effectful.Concurrent.Effect.Concurrent Effectful.Internal.Effect.:> es) => GHC.Base.Applicative (Effectful.Concurrent.Async.Concurrently es) instance (Effectful.Concurrent.Effect.Concurrent Effectful.Internal.Effect.:> es) => GHC.Base.Alternative (Effectful.Concurrent.Async.Concurrently es) instance (Effectful.Concurrent.Effect.Concurrent Effectful.Internal.Effect.:> es, GHC.Base.Semigroup a) => GHC.Base.Semigroup (Effectful.Concurrent.Async.Concurrently es a) instance (Effectful.Concurrent.Effect.Concurrent Effectful.Internal.Effect.:> es, GHC.Base.Monoid a) => GHC.Base.Monoid (Effectful.Concurrent.Async.Concurrently es a) instance GHC.Base.Applicative (Effectful.Concurrent.Async.Conc es) instance GHC.Base.Alternative (Effectful.Concurrent.Async.Conc es) instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Effectful.Concurrent.Async.Conc es a) instance GHC.Base.Monoid a => GHC.Base.Monoid (Effectful.Concurrent.Async.Conc es a) -- | Lifted Control.Concurrent. -- -- For functions that spawn threads, the order of preference for their -- usage is recommended as follows: -- -- 1) High level functions from Effectful.Concurrent.Async such as -- withAsync, concurrently or mapConcurrently. -- -- 2) Low level functions from Effectful.Concurrent.Async such as -- async. -- -- 3) Low level functions from Effectful.Concurrent such as -- forkIO. module Effectful.Concurrent -- | Provide the ability to run Eff computations concurrently in -- multiple threads and communicate between them. -- -- Warning: unless you stick to high level functions from the -- withAsync family, the Concurrent effect makes it -- possible to escape the scope of any scoped effect operation. Consider -- the following: -- --
--   >>> import qualified Effectful.Reader.Static as R
--   
-- --
--   >>> printAsk msg = liftIO . putStrLn . (msg ++) . (": " ++) =<< R.ask
--   
-- --
--   >>> :{
--     runEff . R.runReader "GLOBAL" . runConcurrent $ do
--       a <- R.local (const "LOCAL") $ do
--         a <- async $ do
--           printAsk "child (first)"
--           threadDelay 20000
--           printAsk "child (second)"
--         threadDelay 10000
--         printAsk "parent (inside)"
--         pure a
--       printAsk "parent (outside)"
--       wait a
--   :}
--   child (first): LOCAL
--   parent (inside): LOCAL
--   parent (outside): GLOBAL
--   child (second): LOCAL
--   
-- -- Note that the asynchronous computation doesn't respect the scope of -- local, i.e. the child thread still behaves like it's inside the -- local block, even though the parent thread already got out of -- it. -- -- This is because the value provided by the Reader effect is -- thread local, i.e. each thread manages its own version of it. For the -- Reader it is the only reasonable behavior, it wouldn't be very -- useful if its "read only" value was affected by calls to local -- from its parent or child threads. -- -- However, the cut isn't so clear if it comes to effects that provide -- access to a mutable state. That's why statically dispatched -- State and Writer effects come in two flavors, local -- and shared: -- --
--   >>> import qualified Effectful.State.Static.Local as SL
--   
--   >>> :{
--     runEff . SL.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SL.modify (++ "!")
--   :}
--   "Hi"
--   
-- --
--   >>> import qualified Effectful.State.Static.Shared as SS
--   
--   >>> :{
--     runEff . SS.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SS.modify (++ "!")
--   :}
--   "Hi!!!"
--   
-- -- In the first example state updates made concurrently are not reflected -- in the parent thread because the value is thread local, but in the -- second example they are, because the value is shared. data Concurrent :: Effect -- | Run the Concurrent effect. runConcurrent :: IOE :> es => Eff (Concurrent : es) a -> Eff es a -- | Lifted myThreadId. myThreadId :: Concurrent :> es => Eff es ThreadId -- | Lifted forkIO. forkIO :: Concurrent :> es => Eff es () -> Eff es ThreadId -- | Lifted forkFinally. forkFinally :: Concurrent :> es => Eff es a -> (Either SomeException a -> Eff es ()) -> Eff es ThreadId -- | Lifted forkIOWithUnmask. forkIOWithUnmask :: Concurrent :> es => ((forall a. Eff es a -> Eff es a) -> Eff es ()) -> Eff es ThreadId -- | Lifted killThread. killThread :: Concurrent :> es => ThreadId -> Eff es () -- | Lifted throwTo. throwTo :: (Concurrent :> es, Exception e) => ThreadId -> e -> Eff es () -- | Lifted forkOn. forkOn :: Concurrent :> es => Int -> Eff es () -> Eff es ThreadId -- | Lifted forkOnWithUnmask. forkOnWithUnmask :: Concurrent :> es => Int -> ((forall a. Eff es a -> Eff es a) -> Eff es ()) -> Eff es ThreadId -- | Lifted getNumCapabilities. getNumCapabilities :: Concurrent :> es => Eff es Int -- | Lifted setNumCapabilities. setNumCapabilities :: Concurrent :> es => Int -> Eff es () -- | Lifted getNumProcessors. getNumProcessors :: Concurrent :> es => Eff es Int -- | Lifted threadCapability. threadCapability :: Concurrent :> es => ThreadId -> Eff es (Int, Bool) -- | Lifted yield. yield :: Concurrent :> es => Eff es () -- | Lifted threadDelay. threadDelay :: Concurrent :> es => Int -> Eff es () -- | Lifted threadWaitRead. threadWaitRead :: Concurrent :> es => Fd -> Eff es () -- | Lifted threadWaitWrite. threadWaitWrite :: Concurrent :> es => Fd -> Eff es () -- | Lifted threadWaitReadSTM. threadWaitReadSTM :: Concurrent :> es => Fd -> Eff es (STM (), Eff es ()) -- | Lifted threadWaitWriteSTM. threadWaitWriteSTM :: Concurrent :> es => Fd -> Eff es (STM (), Eff es ()) -- | Lifted forkOS. forkOS :: Concurrent :> es => Eff es () -> Eff es ThreadId -- | Lifted forkOSWithUnmask. forkOSWithUnmask :: Concurrent :> es => ((forall a. Eff es a -> Eff es a) -> Eff es ()) -> Eff es ThreadId -- | Lifted isCurrentThreadBound. isCurrentThreadBound :: Concurrent :> es => Eff es Bool -- | Lifted runInBoundThread. runInBoundThread :: Concurrent :> es => Eff es a -> Eff es a -- | Lifted runInUnboundThread. runInUnboundThread :: Concurrent :> es => Eff es a -> Eff es a -- | Lifted mkWeakThreadId. mkWeakThreadId :: Concurrent :> es => ThreadId -> Eff es (Weak ThreadId) -- | True if bound threads are supported. If -- rtsSupportsBoundThreads is False, -- isCurrentThreadBound will always return False and both -- forkOS and runInBoundThread will fail. rtsSupportsBoundThreads :: Bool -- | Lifted Control.Concurrent.MVar. module Effectful.Concurrent.MVar -- | Provide the ability to run Eff computations concurrently in -- multiple threads and communicate between them. -- -- Warning: unless you stick to high level functions from the -- withAsync family, the Concurrent effect makes it -- possible to escape the scope of any scoped effect operation. Consider -- the following: -- --
--   >>> import qualified Effectful.Reader.Static as R
--   
-- --
--   >>> printAsk msg = liftIO . putStrLn . (msg ++) . (": " ++) =<< R.ask
--   
-- --
--   >>> :{
--     runEff . R.runReader "GLOBAL" . runConcurrent $ do
--       a <- R.local (const "LOCAL") $ do
--         a <- async $ do
--           printAsk "child (first)"
--           threadDelay 20000
--           printAsk "child (second)"
--         threadDelay 10000
--         printAsk "parent (inside)"
--         pure a
--       printAsk "parent (outside)"
--       wait a
--   :}
--   child (first): LOCAL
--   parent (inside): LOCAL
--   parent (outside): GLOBAL
--   child (second): LOCAL
--   
-- -- Note that the asynchronous computation doesn't respect the scope of -- local, i.e. the child thread still behaves like it's inside the -- local block, even though the parent thread already got out of -- it. -- -- This is because the value provided by the Reader effect is -- thread local, i.e. each thread manages its own version of it. For the -- Reader it is the only reasonable behavior, it wouldn't be very -- useful if its "read only" value was affected by calls to local -- from its parent or child threads. -- -- However, the cut isn't so clear if it comes to effects that provide -- access to a mutable state. That's why statically dispatched -- State and Writer effects come in two flavors, local -- and shared: -- --
--   >>> import qualified Effectful.State.Static.Local as SL
--   
--   >>> :{
--     runEff . SL.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SL.modify (++ "!")
--   :}
--   "Hi"
--   
-- --
--   >>> import qualified Effectful.State.Static.Shared as SS
--   
--   >>> :{
--     runEff . SS.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SS.modify (++ "!")
--   :}
--   "Hi!!!"
--   
-- -- In the first example state updates made concurrently are not reflected -- in the parent thread because the value is thread local, but in the -- second example they are, because the value is shared. data Concurrent :: Effect -- | Run the Concurrent effect. runConcurrent :: IOE :> es => Eff (Concurrent : es) a -> Eff es a -- | An MVar (pronounced "em-var") is a synchronising variable, used -- for communication between concurrent threads. It can be thought of as -- a box, which may be empty or full. data MVar a -- | Lifted newEmptyMVar. newEmptyMVar :: Concurrent :> es => Eff es (MVar a) -- | Lifted newMVar. newMVar :: Concurrent :> es => a -> Eff es (MVar a) -- | Lifted takeMVar. takeMVar :: Concurrent :> es => MVar a -> Eff es a -- | Lifted putMVar. putMVar :: Concurrent :> es => MVar a -> a -> Eff es () -- | Lifted readMVar. readMVar :: Concurrent :> es => MVar a -> Eff es a -- | Lifted swapMVar. swapMVar :: Concurrent :> es => MVar a -> a -> Eff es a -- | Lifted tryTakeMVar. tryTakeMVar :: Concurrent :> es => MVar a -> Eff es (Maybe a) -- | Lifted tryPutMVar. tryPutMVar :: Concurrent :> es => MVar a -> a -> Eff es Bool -- | Lifted isEmptyMVar. isEmptyMVar :: Concurrent :> es => MVar a -> Eff es Bool -- | Lifted withMVar. withMVar :: Concurrent :> es => MVar a -> (a -> Eff es b) -> Eff es b -- | Lifted withMVarMasked. withMVarMasked :: Concurrent :> es => MVar a -> (a -> Eff es b) -> Eff es b -- | Lifted modifyMVar. modifyMVar :: Concurrent :> es => MVar a -> (a -> Eff es (a, b)) -> Eff es b -- | Lifted modifyMVar_. modifyMVar_ :: Concurrent :> es => MVar a -> (a -> Eff es a) -> Eff es () -- | Lifted modifyMVarMasked. modifyMVarMasked :: Concurrent :> es => MVar a -> (a -> Eff es (a, b)) -> Eff es b -- | Lifted modifyMVarMasked_. modifyMVarMasked_ :: Concurrent :> es => MVar a -> (a -> Eff es a) -> Eff es () -- | Lifted tryReadMVar. tryReadMVar :: Concurrent :> es => MVar a -> Eff es (Maybe a) -- | Lifted mkWeakMVar. mkWeakMVar :: Concurrent :> es => MVar a -> Eff es () -> Eff es (Weak (MVar a)) -- | Lifted Control.Concurrent.MVar with operations that force -- values put inside an MVar to WHNF. module Effectful.Concurrent.MVar.Strict -- | Provide the ability to run Eff computations concurrently in -- multiple threads and communicate between them. -- -- Warning: unless you stick to high level functions from the -- withAsync family, the Concurrent effect makes it -- possible to escape the scope of any scoped effect operation. Consider -- the following: -- --
--   >>> import qualified Effectful.Reader.Static as R
--   
-- --
--   >>> printAsk msg = liftIO . putStrLn . (msg ++) . (": " ++) =<< R.ask
--   
-- --
--   >>> :{
--     runEff . R.runReader "GLOBAL" . runConcurrent $ do
--       a <- R.local (const "LOCAL") $ do
--         a <- async $ do
--           printAsk "child (first)"
--           threadDelay 20000
--           printAsk "child (second)"
--         threadDelay 10000
--         printAsk "parent (inside)"
--         pure a
--       printAsk "parent (outside)"
--       wait a
--   :}
--   child (first): LOCAL
--   parent (inside): LOCAL
--   parent (outside): GLOBAL
--   child (second): LOCAL
--   
-- -- Note that the asynchronous computation doesn't respect the scope of -- local, i.e. the child thread still behaves like it's inside the -- local block, even though the parent thread already got out of -- it. -- -- This is because the value provided by the Reader effect is -- thread local, i.e. each thread manages its own version of it. For the -- Reader it is the only reasonable behavior, it wouldn't be very -- useful if its "read only" value was affected by calls to local -- from its parent or child threads. -- -- However, the cut isn't so clear if it comes to effects that provide -- access to a mutable state. That's why statically dispatched -- State and Writer effects come in two flavors, local -- and shared: -- --
--   >>> import qualified Effectful.State.Static.Local as SL
--   
--   >>> :{
--     runEff . SL.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SL.modify (++ "!")
--   :}
--   "Hi"
--   
-- --
--   >>> import qualified Effectful.State.Static.Shared as SS
--   
--   >>> :{
--     runEff . SS.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SS.modify (++ "!")
--   :}
--   "Hi!!!"
--   
-- -- In the first example state updates made concurrently are not reflected -- in the parent thread because the value is thread local, but in the -- second example they are, because the value is shared. data Concurrent :: Effect -- | Run the Concurrent effect. runConcurrent :: IOE :> es => Eff (Concurrent : es) a -> Eff es a -- | An MVar (pronounced "em-var") is a synchronising variable, used -- for communication between concurrent threads. It can be thought of as -- a box, which may be empty or full. data MVar a -- | Lifted newEmptyMVar. newEmptyMVar :: Concurrent :> es => Eff es (MVar a) -- | Lifted newMVar that evaluates the value to WHNF. newMVar :: Concurrent :> es => a -> Eff es (MVar a) -- | Lifted takeMVar. takeMVar :: Concurrent :> es => MVar a -> Eff es a -- | Lifted putMVar. putMVar :: Concurrent :> es => MVar a -> a -> Eff es () -- | Lifted readMVar. readMVar :: Concurrent :> es => MVar a -> Eff es a -- | Lifted swapMVar that evaluates the new value to WHNF. swapMVar :: Concurrent :> es => MVar a -> a -> Eff es a -- | Lifted tryTakeMVar. tryTakeMVar :: Concurrent :> es => MVar a -> Eff es (Maybe a) -- | Lifted tryPutMVar that evaluates the new value to WHNF. tryPutMVar :: Concurrent :> es => MVar a -> a -> Eff es Bool -- | Lifted isEmptyMVar. isEmptyMVar :: Concurrent :> es => MVar a -> Eff es Bool -- | Lifted withMVar. withMVar :: Concurrent :> es => MVar a -> (a -> Eff es b) -> Eff es b -- | Lifted withMVarMasked. withMVarMasked :: Concurrent :> es => MVar a -> (a -> Eff es b) -> Eff es b -- | Lifted modifyMVar that evaluates the new value to WHNF. modifyMVar :: Concurrent :> es => MVar a -> (a -> Eff es (a, b)) -> Eff es b -- | Lifted modifyMVar_ that evaluates the new value to WHNF. modifyMVar_ :: Concurrent :> es => MVar a -> (a -> Eff es a) -> Eff es () -- | Lifted modifyMVarMasked that evaluates the new value to WHNF. modifyMVarMasked :: Concurrent :> es => MVar a -> (a -> Eff es (a, b)) -> Eff es b -- | Lifted modifyMVarMasked_ that evaluates the new value to WHNF. modifyMVarMasked_ :: Concurrent :> es => MVar a -> (a -> Eff es a) -> Eff es () -- | Lifted tryReadMVar. tryReadMVar :: Concurrent :> es => MVar a -> Eff es (Maybe a) -- | Lifted mkWeakMVar. mkWeakMVar :: Concurrent :> es => MVar a -> Eff es () -> Eff es (Weak (MVar a)) -- | Lifted Control.Concurrent.QSem. module Effectful.Concurrent.QSem -- | Provide the ability to run Eff computations concurrently in -- multiple threads and communicate between them. -- -- Warning: unless you stick to high level functions from the -- withAsync family, the Concurrent effect makes it -- possible to escape the scope of any scoped effect operation. Consider -- the following: -- --
--   >>> import qualified Effectful.Reader.Static as R
--   
-- --
--   >>> printAsk msg = liftIO . putStrLn . (msg ++) . (": " ++) =<< R.ask
--   
-- --
--   >>> :{
--     runEff . R.runReader "GLOBAL" . runConcurrent $ do
--       a <- R.local (const "LOCAL") $ do
--         a <- async $ do
--           printAsk "child (first)"
--           threadDelay 20000
--           printAsk "child (second)"
--         threadDelay 10000
--         printAsk "parent (inside)"
--         pure a
--       printAsk "parent (outside)"
--       wait a
--   :}
--   child (first): LOCAL
--   parent (inside): LOCAL
--   parent (outside): GLOBAL
--   child (second): LOCAL
--   
-- -- Note that the asynchronous computation doesn't respect the scope of -- local, i.e. the child thread still behaves like it's inside the -- local block, even though the parent thread already got out of -- it. -- -- This is because the value provided by the Reader effect is -- thread local, i.e. each thread manages its own version of it. For the -- Reader it is the only reasonable behavior, it wouldn't be very -- useful if its "read only" value was affected by calls to local -- from its parent or child threads. -- -- However, the cut isn't so clear if it comes to effects that provide -- access to a mutable state. That's why statically dispatched -- State and Writer effects come in two flavors, local -- and shared: -- --
--   >>> import qualified Effectful.State.Static.Local as SL
--   
--   >>> :{
--     runEff . SL.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SL.modify (++ "!")
--   :}
--   "Hi"
--   
-- --
--   >>> import qualified Effectful.State.Static.Shared as SS
--   
--   >>> :{
--     runEff . SS.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SS.modify (++ "!")
--   :}
--   "Hi!!!"
--   
-- -- In the first example state updates made concurrently are not reflected -- in the parent thread because the value is thread local, but in the -- second example they are, because the value is shared. data Concurrent :: Effect -- | Run the Concurrent effect. runConcurrent :: IOE :> es => Eff (Concurrent : es) a -> Eff es a -- | QSem is a quantity semaphore in which the resource is acquired -- and released in units of one. It provides guaranteed FIFO ordering for -- satisfying blocked waitQSem calls. -- -- The pattern -- --
--   bracket_ waitQSem signalQSem (...)
--   
-- -- is safe; it never loses a unit of the resource. data QSem -- | Lifted newQSem. newQSem :: Concurrent :> es => Int -> Eff es QSem -- | Lifted waitQSem. waitQSem :: Concurrent :> es => QSem -> Eff es () -- | Lifted signalQSem. signalQSem :: Concurrent :> es => QSem -> Eff es () -- | Lifted Control.Concurrent.QSemN. module Effectful.Concurrent.QSemN -- | Provide the ability to run Eff computations concurrently in -- multiple threads and communicate between them. -- -- Warning: unless you stick to high level functions from the -- withAsync family, the Concurrent effect makes it -- possible to escape the scope of any scoped effect operation. Consider -- the following: -- --
--   >>> import qualified Effectful.Reader.Static as R
--   
-- --
--   >>> printAsk msg = liftIO . putStrLn . (msg ++) . (": " ++) =<< R.ask
--   
-- --
--   >>> :{
--     runEff . R.runReader "GLOBAL" . runConcurrent $ do
--       a <- R.local (const "LOCAL") $ do
--         a <- async $ do
--           printAsk "child (first)"
--           threadDelay 20000
--           printAsk "child (second)"
--         threadDelay 10000
--         printAsk "parent (inside)"
--         pure a
--       printAsk "parent (outside)"
--       wait a
--   :}
--   child (first): LOCAL
--   parent (inside): LOCAL
--   parent (outside): GLOBAL
--   child (second): LOCAL
--   
-- -- Note that the asynchronous computation doesn't respect the scope of -- local, i.e. the child thread still behaves like it's inside the -- local block, even though the parent thread already got out of -- it. -- -- This is because the value provided by the Reader effect is -- thread local, i.e. each thread manages its own version of it. For the -- Reader it is the only reasonable behavior, it wouldn't be very -- useful if its "read only" value was affected by calls to local -- from its parent or child threads. -- -- However, the cut isn't so clear if it comes to effects that provide -- access to a mutable state. That's why statically dispatched -- State and Writer effects come in two flavors, local -- and shared: -- --
--   >>> import qualified Effectful.State.Static.Local as SL
--   
--   >>> :{
--     runEff . SL.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SL.modify (++ "!")
--   :}
--   "Hi"
--   
-- --
--   >>> import qualified Effectful.State.Static.Shared as SS
--   
--   >>> :{
--     runEff . SS.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SS.modify (++ "!")
--   :}
--   "Hi!!!"
--   
-- -- In the first example state updates made concurrently are not reflected -- in the parent thread because the value is thread local, but in the -- second example they are, because the value is shared. data Concurrent :: Effect -- | Run the Concurrent effect. runConcurrent :: IOE :> es => Eff (Concurrent : es) a -> Eff es a -- | QSemN is a quantity semaphore in which the resource is acquired -- and released in units of one. It provides guaranteed FIFO ordering for -- satisfying blocked waitQSemN calls. -- -- The pattern -- --
--   bracket_ (waitQSemN n) (signalQSemN n) (...)
--   
-- -- is safe; it never loses any of the resource. data QSemN -- | Lifted newQSemN. newQSemN :: Concurrent :> es => Int -> Eff es QSemN -- | Lifted waitQSemN. waitQSemN :: Concurrent :> es => QSemN -> Int -> Eff es () -- | Lifted signalQSemN. signalQSemN :: Concurrent :> es => QSemN -> Int -> Eff es () -- | Lifted Control.Concurrent.STM. module Effectful.Concurrent.STM -- | Provide the ability to run Eff computations concurrently in -- multiple threads and communicate between them. -- -- Warning: unless you stick to high level functions from the -- withAsync family, the Concurrent effect makes it -- possible to escape the scope of any scoped effect operation. Consider -- the following: -- --
--   >>> import qualified Effectful.Reader.Static as R
--   
-- --
--   >>> printAsk msg = liftIO . putStrLn . (msg ++) . (": " ++) =<< R.ask
--   
-- --
--   >>> :{
--     runEff . R.runReader "GLOBAL" . runConcurrent $ do
--       a <- R.local (const "LOCAL") $ do
--         a <- async $ do
--           printAsk "child (first)"
--           threadDelay 20000
--           printAsk "child (second)"
--         threadDelay 10000
--         printAsk "parent (inside)"
--         pure a
--       printAsk "parent (outside)"
--       wait a
--   :}
--   child (first): LOCAL
--   parent (inside): LOCAL
--   parent (outside): GLOBAL
--   child (second): LOCAL
--   
-- -- Note that the asynchronous computation doesn't respect the scope of -- local, i.e. the child thread still behaves like it's inside the -- local block, even though the parent thread already got out of -- it. -- -- This is because the value provided by the Reader effect is -- thread local, i.e. each thread manages its own version of it. For the -- Reader it is the only reasonable behavior, it wouldn't be very -- useful if its "read only" value was affected by calls to local -- from its parent or child threads. -- -- However, the cut isn't so clear if it comes to effects that provide -- access to a mutable state. That's why statically dispatched -- State and Writer effects come in two flavors, local -- and shared: -- --
--   >>> import qualified Effectful.State.Static.Local as SL
--   
--   >>> :{
--     runEff . SL.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SL.modify (++ "!")
--   :}
--   "Hi"
--   
-- --
--   >>> import qualified Effectful.State.Static.Shared as SS
--   
--   >>> :{
--     runEff . SS.execState "Hi" . runConcurrent $ do
--       replicateConcurrently_ 3 $ SS.modify (++ "!")
--   :}
--   "Hi!!!"
--   
-- -- In the first example state updates made concurrently are not reflected -- in the parent thread because the value is thread local, but in the -- second example they are, because the value is shared. data Concurrent :: Effect -- | Run the Concurrent effect. runConcurrent :: IOE :> es => Eff (Concurrent : es) a -> Eff es a -- | A monad supporting atomic memory transactions. data STM a -- | Lifted atomically. atomically :: Concurrent :> es => STM a -> Eff es a -- | Retry execution of the current memory transaction because it has seen -- values in TVars which mean that it should not continue (e.g. -- the TVars represent a shared buffer that is now empty). The -- implementation may block the thread until one of the TVars that -- it has read from has been updated. (GHC only) retry :: STM a -- | Compose two alternative STM actions (GHC only). -- -- If the first action completes without retrying then it forms the -- result of the orElse. Otherwise, if the first action retries, -- then the second action is tried in its place. If both actions retry -- then the orElse as a whole retries. orElse :: STM a -> STM a -> STM a -- | Check that the boolean condition is true and, if not, retry. -- -- In other words, check b = unless b retry. check :: Bool -> STM () -- | A variant of throw that can only be used within the STM -- monad. -- -- Throwing an exception in STM aborts the transaction and -- propagates the exception. If the exception is caught via -- catchSTM, only the changes enclosed by the catch are rolled -- back; changes made outside of catchSTM persist. -- -- If the exception is not caught inside of the STM, it is -- re-thrown by atomically, and the entire STM is rolled -- back. -- -- Although throwSTM has a type that is an instance of the type of -- throw, the two functions are subtly different: -- --
--   throw e    `seq` x  ===> throw e
--   throwSTM e `seq` x  ===> x
--   
-- -- The first example will cause the exception e to be raised, -- whereas the second one won't. In fact, throwSTM will only cause -- an exception to be raised when it is used within the STM monad. -- The throwSTM variant should be used in preference to -- throw to raise an exception within the STM monad because -- it guarantees ordering with respect to other STM operations, -- whereas throw does not. throwSTM :: Exception e => e -> STM a -- | Exception handling within STM actions. -- -- catchSTM m f catches any exception thrown by -- m using throwSTM, using the function f to -- handle the exception. If an exception is thrown, any changes made by -- m are rolled back, but changes prior to m persist. catchSTM :: Exception e => STM a -> (e -> STM a) -> STM a -- | Shared memory locations that support atomic memory transactions. data TVar a -- | Lifted newTVarIO. newTVarIO :: Concurrent :> es => a -> Eff es (TVar a) -- | Lifted readTVarIO. readTVarIO :: Concurrent :> es => TVar a -> Eff es a -- | Create a new TVar holding a value supplied newTVar :: a -> STM (TVar a) -- | Return the current value stored in a TVar. readTVar :: TVar a -> STM a -- | Write the supplied value into a TVar. writeTVar :: TVar a -> a -> STM () -- | Mutate the contents of a TVar. N.B., this version is -- non-strict. modifyTVar :: TVar a -> (a -> a) -> STM () -- | Strict version of modifyTVar. modifyTVar' :: TVar a -> (a -> a) -> STM () -- | Swap the contents of a TVar for a new value. swapTVar :: TVar a -> a -> STM a -- | Lifted registerDelay. registerDelay :: Concurrent :> es => Int -> Eff es (TVar Bool) -- | Lifted mkWeakTVar. mkWeakTVar :: Concurrent :> es => TVar a -> Eff es () -> Eff es (Weak (TVar a)) -- | A TMVar is a synchronising variable, used for communication -- between concurrent threads. It can be thought of as a box, which may -- be empty or full. data TMVar a -- | Create a TMVar which contains the supplied value. newTMVar :: a -> STM (TMVar a) -- | Create a TMVar which is initially empty. newEmptyTMVar :: STM (TMVar a) -- | Lifted newTMVarIO. newTMVarIO :: Concurrent :> es => a -> Eff es (TMVar a) -- | Lifted newEmptyTMVarIO. newEmptyTMVarIO :: Concurrent :> es => Eff es (TMVar a) -- | Return the contents of the TMVar. If the TMVar is -- currently empty, the transaction will retry. After a -- takeTMVar, the TMVar is left empty. takeTMVar :: TMVar a -> STM a -- | Put a value into a TMVar. If the TMVar is currently -- full, putTMVar will retry. putTMVar :: TMVar a -> a -> STM () -- | This is a combination of takeTMVar and putTMVar; ie. it -- takes the value from the TMVar, puts it back, and also returns -- it. readTMVar :: TMVar a -> STM a -- | A version of readTMVar which does not retry. Instead it returns -- Nothing if no value is available. tryReadTMVar :: TMVar a -> STM (Maybe a) -- | Swap the contents of a TMVar for a new value. swapTMVar :: TMVar a -> a -> STM a -- | A version of takeTMVar that does not retry. The -- tryTakeTMVar function returns Nothing if the -- TMVar was empty, or Just a if the TMVar -- was full with contents a. After tryTakeTMVar, the -- TMVar is left empty. tryTakeTMVar :: TMVar a -> STM (Maybe a) -- | A version of putTMVar that does not retry. The -- tryPutTMVar function attempts to put the value a into -- the TMVar, returning True if it was successful, or -- False otherwise. tryPutTMVar :: TMVar a -> a -> STM Bool -- | Check whether a given TMVar is empty. isEmptyTMVar :: TMVar a -> STM Bool -- | Lifted mkWeakTMVar. mkWeakTMVar :: Concurrent :> es => TMVar a -> Eff es () -> Eff es (Weak (TMVar a)) -- | TChan is an abstract type representing an unbounded FIFO -- channel. data TChan a -- | Build and return a new instance of TChan newTChan :: STM (TChan a) -- | Lifted newTChanIO. newTChanIO :: Concurrent :> es => Eff es (TChan a) -- | Create a write-only TChan. More precisely, readTChan -- will retry even after items have been written to the channel. -- The only way to read a broadcast channel is to duplicate it with -- dupTChan. -- -- Consider a server that broadcasts messages to clients: -- --
--   serve :: TChan Message -> Client -> IO loop
--   serve broadcastChan client = do
--       myChan <- dupTChan broadcastChan
--       forever $ do
--           message <- readTChan myChan
--           send client message
--   
-- -- The problem with using newTChan to create the broadcast channel -- is that if it is only written to and never read, items will pile up in -- memory. By using newBroadcastTChan to create the broadcast -- channel, items can be garbage collected after clients have seen them. newBroadcastTChan :: STM (TChan a) -- | Lifted newBroadcastTChanIO. newBroadcastTChanIO :: Concurrent :> es => Eff es (TChan a) -- | Duplicate a TChan: the duplicate channel begins empty, but data -- written to either channel from then on will be available from both. -- Hence this creates a kind of broadcast channel, where data written by -- anyone is seen by everyone else. dupTChan :: TChan a -> STM (TChan a) -- | Clone a TChan: similar to dupTChan, but the cloned channel -- starts with the same content available as the original channel. cloneTChan :: TChan a -> STM (TChan a) -- | Read the next value from the TChan. readTChan :: TChan a -> STM a -- | A version of readTChan which does not retry. Instead it returns -- Nothing if no value is available. tryReadTChan :: TChan a -> STM (Maybe a) -- | Get the next value from the TChan without removing it, -- retrying if the channel is empty. peekTChan :: TChan a -> STM a -- | A version of peekTChan which does not retry. Instead it returns -- Nothing if no value is available. tryPeekTChan :: TChan a -> STM (Maybe a) -- | Write a value to a TChan. writeTChan :: TChan a -> a -> STM () -- | Put a data item back onto a channel, where it will be the next item -- read. unGetTChan :: TChan a -> a -> STM () -- | Returns True if the supplied TChan is empty. isEmptyTChan :: TChan a -> STM Bool -- | TQueue is an abstract type representing an unbounded FIFO -- channel. data TQueue a -- | Build and returns a new instance of TQueue newTQueue :: STM (TQueue a) -- | Lifted newTQueueIO. newTQueueIO :: Concurrent :> es => Eff es (TQueue a) -- | Read the next value from the TQueue. readTQueue :: TQueue a -> STM a -- | A version of readTQueue which does not retry. Instead it -- returns Nothing if no value is available. tryReadTQueue :: TQueue a -> STM (Maybe a) -- | Get the next value from the TQueue without removing it, -- retrying if the channel is empty. peekTQueue :: TQueue a -> STM a -- | A version of peekTQueue which does not retry. Instead it -- returns Nothing if no value is available. tryPeekTQueue :: TQueue a -> STM (Maybe a) -- | Efficiently read the entire contents of a TQueue into a list. -- This function never retries. flushTQueue :: TQueue a -> STM [a] -- | Write a value to a TQueue. writeTQueue :: TQueue a -> a -> STM () -- | Put a data item back onto a channel, where it will be the next item -- read. unGetTQueue :: TQueue a -> a -> STM () -- | Returns True if the supplied TQueue is empty. isEmptyTQueue :: TQueue a -> STM Bool -- | TBQueue is an abstract type representing a bounded FIFO -- channel. data TBQueue a -- | Builds and returns a new instance of TBQueue. newTBQueue :: Natural -> STM (TBQueue a) -- | Lifted newTBQueueIO. newTBQueueIO :: Concurrent :> es => Natural -> Eff es (TBQueue a) -- | Read the next value from the TBQueue. readTBQueue :: TBQueue a -> STM a -- | A version of readTBQueue which does not retry. Instead it -- returns Nothing if no value is available. tryReadTBQueue :: TBQueue a -> STM (Maybe a) -- | Get the next value from the TBQueue without removing it, -- retrying if the channel is empty. peekTBQueue :: TBQueue a -> STM a -- | A version of peekTBQueue which does not retry. Instead it -- returns Nothing if no value is available. tryPeekTBQueue :: TBQueue a -> STM (Maybe a) -- | Efficiently read the entire contents of a TBQueue into a list. -- This function never retries. flushTBQueue :: TBQueue a -> STM [a] -- | Write a value to a TBQueue; blocks if the queue is full. writeTBQueue :: TBQueue a -> a -> STM () -- | Put a data item back onto a channel, where it will be the next item -- read. Blocks if the queue is full. unGetTBQueue :: TBQueue a -> a -> STM () -- | Return the length of a TBQueue. lengthTBQueue :: TBQueue a -> STM Natural -- | Returns True if the supplied TBQueue is empty. isEmptyTBQueue :: TBQueue a -> STM Bool -- | Returns True if the supplied TBQueue is full. isFullTBQueue :: TBQueue a -> STM Bool module Effectful.Environment -- | An effect for querying and modifying the system environment. data Environment :: Effect -- | Run the Environment effect. runEnvironment :: IOE :> es => Eff (Environment : es) a -> Eff es a -- | Lifted getArgs. getArgs :: Environment :> es => Eff es [String] -- | Lifted getProgName. getProgName :: Environment :> es => Eff es String -- | Lifted getExecutablePath. getExecutablePath :: Environment :> es => Eff es FilePath -- | Lifted getEnv. getEnv :: Environment :> es => String -> Eff es String -- | Lifted getEnvironment. getEnvironment :: Environment :> es => Eff es [(String, String)] -- | Lifted lookupEnv. lookupEnv :: Environment :> es => String -> Eff es (Maybe String) -- | Lifted setEnv. setEnv :: Environment :> es => String -> String -> Eff es () -- | Lifted unsetEnv. unsetEnv :: Environment :> es => String -> Eff es () -- | Lifted withArgs. withArgs :: Environment :> es => [String] -> Eff es a -> Eff es a -- | Lifted withProgName. withProgName :: Environment :> es => String -> Eff es a -> Eff es a module Effectful.FileSystem -- | An effect for interacting with the filesystem. data FileSystem :: Effect -- | Run the FileSystem effect. runFileSystem :: IOE :> es => Eff (FileSystem : es) a -> Eff es a -- | Lifted createDirectory. createDirectory :: FileSystem :> es => FilePath -> Eff es () -- | Lifted createDirectoryIfMissing. createDirectoryIfMissing :: FileSystem :> es => Bool -> FilePath -> Eff es () -- | Lifted removeDirectory. removeDirectory :: FileSystem :> es => FilePath -> Eff es () -- | Lifted removeDirectoryRecursive. removeDirectoryRecursive :: FileSystem :> es => FilePath -> Eff es () -- | Lifted removePathForcibly. removePathForcibly :: FileSystem :> es => FilePath -> Eff es () -- | Lifted renameDirectory. renameDirectory :: FileSystem :> es => FilePath -> FilePath -> Eff es () -- | Lifted listDirectory. listDirectory :: FileSystem :> es => FilePath -> Eff es [FilePath] -- | Lifted getDirectoryContents. getDirectoryContents :: FileSystem :> es => FilePath -> Eff es [FilePath] -- | Lifted getCurrentDirectory. getCurrentDirectory :: FileSystem :> es => Eff es FilePath -- | Lifted setCurrentDirectory. setCurrentDirectory :: FileSystem :> es => FilePath -> Eff es () -- | Lifted withCurrentDirectory. withCurrentDirectory :: FileSystem :> es => FilePath -> Eff es a -> Eff es a -- | Lifted getHomeDirectory. getHomeDirectory :: FileSystem :> es => Eff es FilePath -- | Lifted getXdgDirectory. getXdgDirectory :: FileSystem :> es => XdgDirectory -> FilePath -> Eff es FilePath -- | Lifted getXdgDirectoryList. getXdgDirectoryList :: FileSystem :> es => XdgDirectoryList -> Eff es [FilePath] -- | Lifted getAppUserDataDirectory. getAppUserDataDirectory :: FileSystem :> es => FilePath -> Eff es FilePath -- | Lifted getUserDocumentsDirectory. getUserDocumentsDirectory :: FileSystem :> es => Eff es FilePath -- | Lifted getTemporaryDirectory. getTemporaryDirectory :: FileSystem :> es => Eff es FilePath -- | Lifted removeFile. removeFile :: FileSystem :> es => FilePath -> Eff es () -- | Lifted renameFile. renameFile :: FileSystem :> es => FilePath -> FilePath -> Eff es () -- | Lifted renamePath. renamePath :: FileSystem :> es => FilePath -> FilePath -> Eff es () -- | Lifted copyFile. copyFile :: FileSystem :> es => FilePath -> FilePath -> Eff es () -- | Lifted copyFileWithMetadata. copyFileWithMetadata :: FileSystem :> es => FilePath -> FilePath -> Eff es () -- | Lifted getFileSize. getFileSize :: FileSystem :> es => FilePath -> Eff es Integer -- | Lifted canonicalizePath. canonicalizePath :: FileSystem :> es => FilePath -> Eff es FilePath -- | Lifted makeAbsolute. makeAbsolute :: FileSystem :> es => FilePath -> Eff es FilePath -- | Lifted makeRelativeToCurrentDirectory. makeRelativeToCurrentDirectory :: FileSystem :> es => FilePath -> Eff es FilePath -- | Lifted doesPathExist. doesPathExist :: FileSystem :> es => FilePath -> Eff es Bool -- | Lifted doesFileExist. doesFileExist :: FileSystem :> es => FilePath -> Eff es Bool -- | Lifted doesDirectoryExist. doesDirectoryExist :: FileSystem :> es => FilePath -> Eff es Bool -- | Lifted findExecutable. findExecutable :: FileSystem :> es => String -> Eff es (Maybe FilePath) -- | Lifted findExecutables. findExecutables :: FileSystem :> es => String -> Eff es [FilePath] -- | Lifted findExecutablesInDirectories. findExecutablesInDirectories :: FileSystem :> es => [FilePath] -> String -> Eff es [FilePath] -- | Lifted findFile. findFile :: FileSystem :> es => [FilePath] -> String -> Eff es (Maybe FilePath) -- | Lifted findFiles. findFiles :: FileSystem :> es => [FilePath] -> String -> Eff es [FilePath] -- | Lifted findFileWith. findFileWith :: FileSystem :> es => (FilePath -> Eff es Bool) -> [FilePath] -> String -> Eff es (Maybe FilePath) -- | Lifted findFilesWith. findFilesWith :: FileSystem :> es => (FilePath -> Eff es Bool) -> [FilePath] -> String -> Eff es [FilePath] -- | Lifted createFileLink. createFileLink :: FileSystem :> es => FilePath -> FilePath -> Eff es () -- | Lifted createDirectoryLink. createDirectoryLink :: FileSystem :> es => FilePath -> FilePath -> Eff es () -- | Lifted removeDirectoryLink. removeDirectoryLink :: FileSystem :> es => FilePath -> Eff es () -- | Lifted pathIsSymbolicLink. pathIsSymbolicLink :: FileSystem :> es => FilePath -> Eff es Bool -- | Lifted getSymbolicLinkTarget. getSymbolicLinkTarget :: FileSystem :> es => FilePath -> Eff es FilePath -- | Lifted getPermissions. getPermissions :: FileSystem :> es => FilePath -> Eff es Permissions -- | Lifted setPermissions. setPermissions :: FileSystem :> es => FilePath -> Permissions -> Eff es () -- | Lifted copyPermissions. copyPermissions :: FileSystem :> es => FilePath -> FilePath -> Eff es () -- | Lifted getAccessTime. getAccessTime :: FileSystem :> es => FilePath -> Eff es UTCTime -- | Lifted getModificationTime. getModificationTime :: FileSystem :> es => FilePath -> Eff es UTCTime -- | Lifted setAccessTime. setAccessTime :: FileSystem :> es => FilePath -> UTCTime -> Eff es () -- | Lifted setModificationTime. setModificationTime :: FileSystem :> es => FilePath -> UTCTime -> Eff es () -- | Special directories for storing user-specific application data, -- configuration, and cache files, as specified by the XDG Base -- Directory Specification. -- -- Note: On Windows, XdgData and XdgConfig usually map to -- the same directory. data XdgDirectory -- | For data files (e.g. images). It uses the XDG_DATA_HOME -- environment variable. On non-Windows systems, the default is -- ~/.local/share. On Windows, the default is %APPDATA% -- (e.g. C:/Users/<user>/AppData/Roaming). Can be -- considered as the user-specific equivalent of /usr/share. XdgData :: XdgDirectory -- | For configuration files. It uses the XDG_CONFIG_HOME -- environment variable. On non-Windows systems, the default is -- ~/.config. On Windows, the default is %APPDATA% -- (e.g. C:/Users/<user>/AppData/Roaming). Can be -- considered as the user-specific equivalent of /etc. XdgConfig :: XdgDirectory -- | For non-essential files (e.g. cache). It uses the -- XDG_CACHE_HOME environment variable. On non-Windows systems, -- the default is ~/.cache. On Windows, the default is -- %LOCALAPPDATA% (e.g. -- C:/Users/<user>/AppData/Local). Can be -- considered as the user-specific equivalent of /var/cache. XdgCache :: XdgDirectory -- | Search paths for various application data, as specified by the XDG -- Base Directory Specification. -- -- The list of paths is split using searchPathSeparator, which on -- Windows is a semicolon. -- -- Note: On Windows, XdgDataDirs and XdgConfigDirs usually -- yield the same result. data XdgDirectoryList -- | For data files (e.g. images). It uses the XDG_DATA_DIRS -- environment variable. On non-Windows systems, the default is -- /usr/local/share/ and /usr/share/. On Windows, the -- default is %PROGRAMDATA% or %ALLUSERSPROFILE% (e.g. -- C:/ProgramData). XdgDataDirs :: XdgDirectoryList -- | For configuration files. It uses the XDG_CONFIG_DIRS -- environment variable. On non-Windows systems, the default is -- /etc/xdg. On Windows, the default is %PROGRAMDATA% -- or %ALLUSERSPROFILE% (e.g. C:/ProgramData). XdgConfigDirs :: XdgDirectoryList -- | Filename extension for executable files (including the dot if any) -- (usually "" on POSIX systems and ".exe" on Windows -- or OS/2). exeExtension :: String data Permissions emptyPermissions :: Permissions readable :: Permissions -> Bool writable :: Permissions -> Bool executable :: Permissions -> Bool searchable :: Permissions -> Bool setOwnerReadable :: Bool -> Permissions -> Permissions setOwnerWritable :: Bool -> Permissions -> Permissions setOwnerExecutable :: Bool -> Permissions -> Permissions setOwnerSearchable :: Bool -> Permissions -> Permissions -- | Lifted System.IO. module Effectful.FileSystem.IO -- | An effect for interacting with the filesystem. data FileSystem :: Effect -- | Run the FileSystem effect. runFileSystem :: IOE :> es => Eff (FileSystem : es) a -> Eff es a -- | See openFile data IOMode ReadMode :: IOMode WriteMode :: IOMode AppendMode :: IOMode ReadWriteMode :: IOMode -- | Haskell defines operations to read and write characters from and to -- files, represented by values of type Handle. Each value of -- this type is a handle: a record used by the Haskell run-time -- system to manage I/O with file system objects. A handle has at -- least the following properties: -- -- -- -- Most handles will also have a current I/O position indicating where -- the next input or output operation will occur. A handle is -- readable if it manages only input or both input and output; -- likewise, it is writable if it manages only output or both -- input and output. A handle is open when first allocated. Once -- it is closed it can no longer be used for either input or output, -- though an implementation cannot re-use its storage while references -- remain to it. Handles are in the Show and Eq classes. -- The string produced by showing a handle is system dependent; it should -- include enough information to identify the handle for debugging. A -- handle is equal according to == only to itself; no attempt is -- made to compare the internal state of different handles for equality. data Handle stdin :: Handle stdout :: Handle stderr :: Handle -- | Lifted withFile. withFile :: FileSystem :> es => FilePath -> IOMode -> (Handle -> Eff es a) -> Eff es a -- | Lifted withBinaryFile. withBinaryFile :: FileSystem :> es => FilePath -> IOMode -> (Handle -> Eff es a) -> Eff es a -- | Lifted openFile openFile :: FileSystem :> es => FilePath -> IOMode -> Eff es Handle -- | Lifted hClose hClose :: FileSystem :> es => Handle -> Eff es () -- | Lifted hFlush hFlush :: FileSystem :> es => Handle -> Eff es () -- | Lifted hFileSize hFileSize :: FileSystem :> es => Handle -> Eff es Integer -- | Lifted hSetFileSize hSetFileSize :: FileSystem :> es => Handle -> Integer -> Eff es () -- | Lifted hIsEOF hIsEOF :: FileSystem :> es => Handle -> Eff es Bool -- | Three kinds of buffering are supported: line-buffering, -- block-buffering or no-buffering. These modes have the following -- effects. For output, items are written out, or flushed, from -- the internal buffer according to the buffer mode: -- -- -- -- An implementation is free to flush the buffer more frequently, but not -- less frequently, than specified above. The output buffer is emptied as -- soon as it has been written out. -- -- Similarly, input occurs according to the buffer mode for the handle: -- -- -- -- The default buffering mode when a handle is opened is -- implementation-dependent and may depend on the file system object -- which is attached to that handle. For most implementations, physical -- files will normally be block-buffered and terminals will normally be -- line-buffered. data BufferMode -- | buffering is disabled if possible. NoBuffering :: BufferMode -- | line-buffering should be enabled if possible. LineBuffering :: BufferMode -- | block-buffering should be enabled if possible. The size of the buffer -- is n items if the argument is Just n and is -- otherwise implementation-dependent. BlockBuffering :: Maybe Int -> BufferMode -- | Lifted hSetBuffering hSetBuffering :: FileSystem :> es => Handle -> BufferMode -> Eff es () -- | Lifted hGetBuffering hGetBuffering :: FileSystem :> es => Handle -> Eff es BufferMode -- | Lifted hSeek hSeek :: FileSystem :> es => Handle -> SeekMode -> Integer -> Eff es () -- | A mode that determines the effect of hSeek hdl mode i. data SeekMode -- | the position of hdl is set to i. AbsoluteSeek :: SeekMode -- | the position of hdl is set to offset i from the -- current position. RelativeSeek :: SeekMode -- | the position of hdl is set to offset i from the end -- of the file. SeekFromEnd :: SeekMode -- | Lifted hTell hTell :: FileSystem :> es => Handle -> Eff es Integer -- | Lifted hIsOpen hIsOpen :: FileSystem :> es => Handle -> Eff es Bool -- | Lifted hIsClosed hIsClosed :: FileSystem :> es => Handle -> Eff es Bool -- | Lifted hIsReadable hIsReadable :: FileSystem :> es => Handle -> Eff es Bool -- | Lifted hIsWritable hIsWritable :: FileSystem :> es => Handle -> Eff es Bool -- | Lifted hIsSeekable hIsSeekable :: FileSystem :> es => Handle -> Eff es Bool -- | Lifted hIsTerminalDevice hIsTerminalDevice :: FileSystem :> es => Handle -> Eff es Bool -- | Lifted hSetEcho hSetEcho :: FileSystem :> es => Handle -> Bool -> Eff es () -- | Lifted hGetEcho hGetEcho :: FileSystem :> es => Handle -> Eff es Bool -- | Lifted hWaitForInput hWaitForInput :: FileSystem :> es => Handle -> Int -> Eff es Bool -- | Lifted hReady hReady :: FileSystem :> es => Handle -> Eff es Bool -- | Lifted UnliftIO.IO.File. module Effectful.FileSystem.IO.File -- | Lifted writeBinaryFile. writeBinaryFile :: FileSystem :> es => FilePath -> ByteString -> Eff es () -- | Lifted writeBinaryFileAtomic. writeBinaryFileAtomic :: FileSystem :> es => FilePath -> ByteString -> Eff es () -- | Lifted writeBinaryFileDurable. writeBinaryFileDurable :: FileSystem :> es => FilePath -> ByteString -> Eff es () -- | Lifted writeBinaryFileDurableAtomic. writeBinaryFileDurableAtomic :: FileSystem :> es => FilePath -> ByteString -> Eff es () -- | Lifted withBinaryFile. withBinaryFile :: FileSystem :> es => FilePath -> IOMode -> (Handle -> Eff es a) -> Eff es a -- | Lifted withBinaryFileAtomic. withBinaryFileAtomic :: FileSystem :> es => FilePath -> IOMode -> (Handle -> Eff es a) -> Eff es a -- | Lifted withBinaryFileDurable. withBinaryFileDurable :: FileSystem :> es => FilePath -> IOMode -> (Handle -> Eff es a) -> Eff es a -- | Lifted withBinaryFileDurableAtomic. withBinaryFileDurableAtomic :: FileSystem :> es => FilePath -> IOMode -> (Handle -> Eff es a) -> Eff es a -- | Lifted ensureFileDurable. ensureFileDurable :: FileSystem :> es => FilePath -> Eff es () -- | Lifted System.Process. module Effectful.Process -- | An effect for running child processes using the process -- library. data Process :: Effect runProcess :: IOE :> es => Eff (Process : es) a -> Eff es a -- | Lifted createProcess. createProcess :: Process :> es => CreateProcess -> Eff es (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -- | Lifted createProcess_. createProcess_ :: Process :> es => String -> CreateProcess -> Eff es (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -- | Construct a CreateProcess record for passing to -- createProcess, representing a command to be passed to the -- shell. shell :: String -> CreateProcess -- | Construct a CreateProcess record for passing to -- createProcess, representing a raw command with arguments. -- -- See RawCommand for precise semantics of the specified -- FilePath. proc :: FilePath -> [String] -> CreateProcess data CreateProcess CreateProcess :: CmdSpec -> Maybe FilePath -> Maybe [(String, String)] -> StdStream -> StdStream -> StdStream -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe GroupID -> Maybe UserID -> Bool -> CreateProcess -- | Executable & arguments, or shell command. If cwd is -- Nothing, relative paths are resolved with respect to the -- current working directory. If cwd is provided, it is -- implementation-dependent whether relative paths are resolved with -- respect to cwd or the current working directory, so absolute -- paths should be used to ensure portability. [cmdspec] :: CreateProcess -> CmdSpec -- | Optional path to the working directory for the new process [cwd] :: CreateProcess -> Maybe FilePath -- | Optional environment (otherwise inherit from the current process) [env] :: CreateProcess -> Maybe [(String, String)] -- | How to determine stdin [std_in] :: CreateProcess -> StdStream -- | How to determine stdout [std_out] :: CreateProcess -> StdStream -- | How to determine stderr [std_err] :: CreateProcess -> StdStream -- | Close all file descriptors except stdin, stdout and stderr in the new -- process (on Windows, only works if std_in, std_out, and std_err are -- all Inherit). This implementation will call close an every fd from 3 -- to the maximum of open files, which can be slow for high maximum of -- open files. [close_fds] :: CreateProcess -> Bool -- | Create a new process group [create_group] :: CreateProcess -> Bool -- | Delegate control-C handling. Use this for interactive console -- processes to let them handle control-C themselves (see below for -- details). -- -- On Windows this has no effect. [delegate_ctlc] :: CreateProcess -> Bool -- | Use the windows DETACHED_PROCESS flag when creating the process; does -- nothing on other platforms. [detach_console] :: CreateProcess -> Bool -- | Use the windows CREATE_NEW_CONSOLE flag when creating the process; -- does nothing on other platforms. -- -- Default: False [create_new_console] :: CreateProcess -> Bool -- | Use posix setsid to start the new process in a new session; does -- nothing on other platforms. [new_session] :: CreateProcess -> Bool -- | Use posix setgid to set child process's group id; does nothing on -- other platforms. -- -- Default: Nothing [child_group] :: CreateProcess -> Maybe GroupID -- | Use posix setuid to set child process's user id; does nothing on other -- platforms. -- -- Default: Nothing [child_user] :: CreateProcess -> Maybe UserID -- | On Windows systems this flag indicates that we should wait for the -- entire process tree to finish before unblocking. On POSIX systems this -- flag is ignored. See $exec-on-windows for details. -- -- Default: False [use_process_jobs] :: CreateProcess -> Bool data CmdSpec -- | A command line to execute using the shell ShellCommand :: String -> CmdSpec -- | The name of an executable with a list of arguments -- -- The FilePath argument names the executable, and is interpreted -- according to the platform's standard policy for searching for -- executables. Specifically: -- -- RawCommand :: FilePath -> [String] -> CmdSpec data StdStream -- | Inherit Handle from parent Inherit :: StdStream -- | Use the supplied Handle UseHandle :: Handle -> StdStream -- | Create a new pipe. The returned Handle will use the default -- encoding and newline translation mode (just like Handles -- created by openFile). CreatePipe :: StdStream -- | Close the stream's file descriptor without passing a Handle. On POSIX -- systems this may lead to strange behavior in the child process because -- attempting to read or write after the file has been closed throws an -- error. This should only be used with child processes that don't use -- the file descriptor at all. If you wish to ignore the child process's -- output you should either create a pipe and drain it manually or pass a -- Handle that writes to /dev/null. NoStream :: StdStream -- | A handle to a process, which can be used to wait for termination of -- the process using waitForProcess. -- -- None of the process-creation functions in this library wait for -- termination: they all return a ProcessHandle which may be used -- to wait for the process later. -- -- On Windows a second wait method can be used to block for event -- completion. This requires two handles. A process job handle and a -- events handle to monitor. data ProcessHandle -- | Lifted callProcess. callProcess :: Process :> es => FilePath -> [String] -> Eff es () -- | Lifted callCommand. callCommand :: Process :> es => String -> Eff es () -- | Lifted spawnProcess. spawnProcess :: Process :> es => FilePath -> [String] -> Eff es ProcessHandle -- | Lifted spawnCommand. spawnCommand :: Process :> es => String -> Eff es ProcessHandle -- | Lifted readCreateProcess. readCreateProcess :: Process :> es => CreateProcess -> String -> Eff es String -- | Lifted readProcess. readProcess :: Process :> es => FilePath -> [String] -> String -> Eff es String -- | Lifted readCreateProcessWithExitCode. readCreateProcessWithExitCode :: Process :> es => CreateProcess -> String -> Eff es (ExitCode, String, String) -- | Lifted readProcessWithExitCode. readProcessWithExitCode :: Process :> es => FilePath -> [String] -> String -> Eff es (ExitCode, String, String) -- | Lifted withCreateProcess. withCreateProcess :: Process :> es => CreateProcess -> (Maybe Handle -> Maybe Handle -> Maybe Handle -> ProcessHandle -> Eff es a) -> Eff es a -- | Lifted cleanupProcess. cleanupProcess :: Process :> es => (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> Eff es () -- | Given a program p and arguments args, -- showCommandForUser p args returns a string -- suitable for pasting into /bin/sh (on Unix systems) or -- CMD.EXE (on Windows). showCommandForUser :: FilePath -> [String] -> String -- | The platform specific type for a process identifier. -- -- This is always an integral type. Width and signedness are platform -- specific. type Pid = CPid -- | Lifted getPid. getPid :: Process :> es => ProcessHandle -> Eff es (Maybe Pid) -- | Lifted getCurrentPid. getCurrentPid :: Process :> es => Eff es Pid -- | Lifted waitForProcess. waitForProcess :: Process :> es => ProcessHandle -> Eff es ExitCode -- | Lifted getProcessExitCode. getProcessExitCode :: Process :> es => ProcessHandle -> Eff es (Maybe ExitCode) -- | Lifted terminateProcess. terminateProcess :: Process :> es => ProcessHandle -> Eff es () -- | Lifted interruptProcessGroupOf. interruptProcessGroupOf :: Process :> es => ProcessHandle -> Eff es () -- | Lifted createPipe. createPipe :: Process :> es => Eff es (Handle, Handle) -- | Lifted createPipeFd. createPipeFd :: Process :> es => Eff es (FD, FD) module Effectful.Temporary -- | An effect for interacting with temporary files. data Temporary :: Effect -- | Run the Temporary effect. runTemporary :: IOE :> es => Eff (Temporary : es) a -> Eff es a -- | Lifted withSystemTempFile. withSystemTempFile :: Temporary :> es => String -> (FilePath -> Handle -> Eff es a) -> Eff es a -- | Lifted withSystemTempDirectory. withSystemTempDirectory :: Temporary :> es => String -> (FilePath -> Eff es a) -> Eff es a -- | Lifted withTempFile. withTempFile :: Temporary :> es => FilePath -> String -> (FilePath -> Handle -> Eff es a) -> Eff es a -- | Lifted withTempDirectory. withTempDirectory :: Temporary :> es => FilePath -> String -> (FilePath -> Eff es a) -> Eff es a module Effectful.Timeout -- | An effect for timing out computations. data Timeout :: Effect -- | Run the Timeout effect. runTimeout :: IOE :> es => Eff (Timeout : es) a -> Eff es a -- | Lifted timeout. timeout :: Timeout :> es => Int -> Eff es a -> Eff es (Maybe a)