{-# LANGUAGE UndecidableInstances #-}
-- | Lifted "Control.Concurrent.Async".
module Effectful.Concurrent.Async
  ( -- * Effect
    Concurrent

    -- ** Handlers
  , runConcurrent

    -- * Asynchronous actions
  , Async

    -- * High-level API

    -- ** Spawning with automatic 'cancel'ation
  , withAsync, withAsyncBound, withAsyncOn, withAsyncWithUnmask
  , withAsyncOnWithUnmask

    -- ** Querying 'Async's
  , wait, poll, waitCatch, A.asyncThreadId
  , cancel, uninterruptibleCancel, cancelWith, A.AsyncCancelled(..)
  , A.compareAsyncs

    -- ** High-level utilities
  , race, race_
  , concurrently, concurrently_
  , mapConcurrently, forConcurrently
  , mapConcurrently_, forConcurrently_
  , replicateConcurrently, replicateConcurrently_

    -- *** Concurrently
  , Concurrently(..)

    -- *** Conc
  , Conc, conc, runConc, U.ConcException(..)

    -- ** Pooled concurrency
  , pooledMapConcurrentlyN
  , pooledMapConcurrently
  , pooledMapConcurrentlyN_
  , pooledMapConcurrently_
  , pooledForConcurrentlyN
  , pooledForConcurrently
  , pooledForConcurrentlyN_
  , pooledForConcurrently_
  , pooledReplicateConcurrentlyN
  , pooledReplicateConcurrently
  , pooledReplicateConcurrentlyN_
  , pooledReplicateConcurrently_

    -- ** Specialised operations

    -- *** STM operations
  , A.waitSTM, A.pollSTM, A.waitCatchSTM

    -- *** Waiting for multiple 'Async's
  , waitAny, waitAnyCatch, waitAnyCancel, waitAnyCatchCancel
  , waitEither, waitEitherCatch, waitEitherCancel, waitEitherCatchCancel
  , waitEither_
  , waitBoth

    -- *** Waiting for multiple 'Async's in STM
  , A.waitAnySTM, A.waitAnyCatchSTM
  , A.waitEitherSTM, A.waitEitherCatchSTM
  , A.waitEitherSTM_
  , A.waitBothSTM

    -- * Low-level API

    -- ** Spawning (low-level API)
  , async, asyncBound, asyncOn, asyncWithUnmask, asyncOnWithUnmask

    -- ** Linking
  , link, linkOnly, link2, link2Only, A.ExceptionInLinkedThread(..)
  ) where

import Control.Applicative
import Control.Concurrent (threadDelay)
import Control.Concurrent.Async (Async)
import Control.Exception (Exception, SomeException)
import Control.Monad (forever)
import Data.Kind (Type)
import qualified Control.Concurrent.Async as A
import qualified UnliftIO.Async as U
import qualified UnliftIO.Internals.Async as I

import Effectful
import Effectful.Concurrent.Effect
import Effectful.Dispatch.Static
import Effectful.Dispatch.Static.Primitive
import Effectful.Dispatch.Static.Unsafe

-- | Lifted 'A.async'.
async :: Concurrent :> es => Eff es a -> Eff es (Async a)
async :: Eff es a -> Eff es (Async a)
async = (IO a -> IO (Async a)) -> Eff es a -> Eff es (Async a)
forall a (es :: [Effect]).
(IO a -> IO (Async a)) -> Eff es a -> Eff es (Async a)
liftAsync IO a -> IO (Async a)
forall a. IO a -> IO (Async a)
A.async

-- | Lifted 'A.asyncBound'.
asyncBound :: Concurrent :> es => Eff es a -> Eff es (Async a)
asyncBound :: Eff es a -> Eff es (Async a)
asyncBound = (IO a -> IO (Async a)) -> Eff es a -> Eff es (Async a)
forall a (es :: [Effect]).
(IO a -> IO (Async a)) -> Eff es a -> Eff es (Async a)
liftAsync IO a -> IO (Async a)
forall a. IO a -> IO (Async a)
A.asyncBound

-- | Lifted 'A.asyncOn'.
asyncOn :: Concurrent :> es => Int -> Eff es a -> Eff es (Async a)
asyncOn :: Int -> Eff es a -> Eff es (Async a)
asyncOn Int
cpu = (IO a -> IO (Async a)) -> Eff es a -> Eff es (Async a)
forall a (es :: [Effect]).
(IO a -> IO (Async a)) -> Eff es a -> Eff es (Async a)
liftAsync (Int -> IO a -> IO (Async a)
forall a. Int -> IO a -> IO (Async a)
A.asyncOn Int
cpu)

-- | Lifted 'A.asyncWithUnmask'.
asyncWithUnmask
  :: Concurrent :> es
  => ((forall b. Eff es b -> Eff es b) -> Eff es a)
  -> Eff es (Async a)
asyncWithUnmask :: ((forall b. Eff es b -> Eff es b) -> Eff es a) -> Eff es (Async a)
asyncWithUnmask = (((forall b. IO b -> IO b) -> IO a) -> IO (Async a))
-> ((forall b. Eff es b -> Eff es b) -> Eff es a)
-> Eff es (Async a)
forall a (es :: [Effect]).
(((forall b. IO b -> IO b) -> IO a) -> IO (Async a))
-> ((forall b. Eff es b -> Eff es b) -> Eff es a)
-> Eff es (Async a)
liftAsyncWithUnmask ((forall b. IO b -> IO b) -> IO a) -> IO (Async a)
forall a. ((forall b. IO b -> IO b) -> IO a) -> IO (Async a)
A.asyncWithUnmask

-- | Lifted 'A.asyncOnWithUnmask'.
asyncOnWithUnmask
  :: Concurrent :> es
  => Int
  -> ((forall b. Eff es b -> Eff es b) -> Eff es a)
  -> Eff es (Async a)
asyncOnWithUnmask :: Int
-> ((forall b. Eff es b -> Eff es b) -> Eff es a)
-> Eff es (Async a)
asyncOnWithUnmask Int
cpu = (((forall b. IO b -> IO b) -> IO a) -> IO (Async a))
-> ((forall b. Eff es b -> Eff es b) -> Eff es a)
-> Eff es (Async a)
forall a (es :: [Effect]).
(((forall b. IO b -> IO b) -> IO a) -> IO (Async a))
-> ((forall b. Eff es b -> Eff es b) -> Eff es a)
-> Eff es (Async a)
liftAsyncWithUnmask (Int -> ((forall b. IO b -> IO b) -> IO a) -> IO (Async a)
forall a. Int -> ((forall b. IO b -> IO b) -> IO a) -> IO (Async a)
A.asyncOnWithUnmask Int
cpu)

-- | Lifted 'A.withAsync'.
withAsync
  :: Concurrent :> es
  => Eff es a
  -> (Async a -> Eff es b)
  -> Eff es b
withAsync :: Eff es a -> (Async a -> Eff es b) -> Eff es b
withAsync = (IO a -> (Async a -> IO b) -> IO b)
-> Eff es a -> (Async a -> Eff es b) -> Eff es b
forall a b (es :: [Effect]).
(IO a -> (Async a -> IO b) -> IO b)
-> Eff es a -> (Async a -> Eff es b) -> Eff es b
liftWithAsync IO a -> (Async a -> IO b) -> IO b
forall a b. IO a -> (Async a -> IO b) -> IO b
A.withAsync

-- | Lifted 'A.withAsyncBound'.
withAsyncBound
  :: Concurrent :> es
  => Eff es a
  -> (Async a -> Eff es b)
  -> Eff es b
withAsyncBound :: Eff es a -> (Async a -> Eff es b) -> Eff es b
withAsyncBound = (IO a -> (Async a -> IO b) -> IO b)
-> Eff es a -> (Async a -> Eff es b) -> Eff es b
forall a b (es :: [Effect]).
(IO a -> (Async a -> IO b) -> IO b)
-> Eff es a -> (Async a -> Eff es b) -> Eff es b
liftWithAsync IO a -> (Async a -> IO b) -> IO b
forall a b. IO a -> (Async a -> IO b) -> IO b
A.withAsyncBound

-- | Lifted 'A.withAsyncOn'.
withAsyncOn
  :: Concurrent :> es
  => Int
  -> Eff es a
  -> (Async a -> Eff es b)
  -> Eff es b
withAsyncOn :: Int -> Eff es a -> (Async a -> Eff es b) -> Eff es b
withAsyncOn Int
cpu = (IO a -> (Async a -> IO b) -> IO b)
-> Eff es a -> (Async a -> Eff es b) -> Eff es b
forall a b (es :: [Effect]).
(IO a -> (Async a -> IO b) -> IO b)
-> Eff es a -> (Async a -> Eff es b) -> Eff es b
liftWithAsync (Int -> IO a -> (Async a -> IO b) -> IO b
forall a b. Int -> IO a -> (Async a -> IO b) -> IO b
A.withAsyncOn Int
cpu)

-- | Lifted 'A.withAsyncWithUnmask'.
withAsyncWithUnmask
  :: Concurrent :> es
  => ((forall c. Eff es c -> Eff es c) -> Eff es a)
  -> (Async a -> Eff es b)
  -> Eff es b
withAsyncWithUnmask :: ((forall c. Eff es c -> Eff es c) -> Eff es a)
-> (Async a -> Eff es b) -> Eff es b
withAsyncWithUnmask = (((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b)
-> ((forall c. Eff es c -> Eff es c) -> Eff es a)
-> (Async a -> Eff es b)
-> Eff es b
forall a b (es :: [Effect]).
(((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b)
-> ((forall c. Eff es c -> Eff es c) -> Eff es a)
-> (Async a -> Eff es b)
-> Eff es b
liftWithAsyncWithUnmask ((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b
forall a b.
((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b
A.withAsyncWithUnmask

-- | Lifted 'A.withAsyncOnWithUnmask'.
withAsyncOnWithUnmask
  :: Concurrent :> es
  => Int
  -> ((forall c. Eff es c -> Eff es c) -> Eff es a)
  -> (Async a -> Eff es b)
  -> Eff es b
withAsyncOnWithUnmask :: Int
-> ((forall c. Eff es c -> Eff es c) -> Eff es a)
-> (Async a -> Eff es b)
-> Eff es b
withAsyncOnWithUnmask Int
cpu = (((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b)
-> ((forall c. Eff es c -> Eff es c) -> Eff es a)
-> (Async a -> Eff es b)
-> Eff es b
forall a b (es :: [Effect]).
(((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b)
-> ((forall c. Eff es c -> Eff es c) -> Eff es a)
-> (Async a -> Eff es b)
-> Eff es b
liftWithAsyncWithUnmask (Int
-> ((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b
forall a b.
Int
-> ((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b
A.withAsyncOnWithUnmask Int
cpu)

-- | Lifted 'A.wait'.
wait :: Concurrent :> es => Async a -> Eff es a
wait :: Async a -> Eff es a
wait = IO a -> Eff es a
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO a -> Eff es a) -> (Async a -> IO a) -> Async a -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Async a -> IO a
forall a. Async a -> IO a
A.wait

-- | Lifted 'A.poll'.
poll
  :: Concurrent :> es
  => Async a
  -> Eff es (Maybe (Either SomeException a))
poll :: Async a -> Eff es (Maybe (Either SomeException a))
poll = IO (Maybe (Either SomeException a))
-> Eff es (Maybe (Either SomeException a))
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (Maybe (Either SomeException a))
 -> Eff es (Maybe (Either SomeException a)))
-> (Async a -> IO (Maybe (Either SomeException a)))
-> Async a
-> Eff es (Maybe (Either SomeException a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Async a -> IO (Maybe (Either SomeException a))
forall a. Async a -> IO (Maybe (Either SomeException a))
A.poll

-- | Lifted 'A.cancel'.
cancel :: Concurrent :> es => Async a -> Eff es ()
cancel :: Async a -> Eff es ()
cancel = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (Async a -> IO ()) -> Async a -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Async a -> IO ()
forall a. Async a -> IO ()
A.cancel

-- | Lifted 'A.cancelWith'.
cancelWith :: (Exception e, Concurrent :> es) => Async a -> e -> Eff es ()
cancelWith :: Async a -> e -> Eff es ()
cancelWith Async a
a = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (e -> IO ()) -> e -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Async a -> e -> IO ()
forall e a. Exception e => Async a -> e -> IO ()
A.cancelWith Async a
a

-- | Lifted 'A.uninterruptibleCancel'.
uninterruptibleCancel :: Concurrent :> es => Async a -> Eff es ()
uninterruptibleCancel :: Async a -> Eff es ()
uninterruptibleCancel = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (Async a -> IO ()) -> Async a -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Async a -> IO ()
forall a. Async a -> IO ()
A.uninterruptibleCancel

-- | Lifted 'A.waitCatch'.
waitCatch
  :: Concurrent :> es
  => Async a
  -> Eff es (Either SomeException a)
waitCatch :: Async a -> Eff es (Either SomeException a)
waitCatch = IO (Either SomeException a) -> Eff es (Either SomeException a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (Either SomeException a) -> Eff es (Either SomeException a))
-> (Async a -> IO (Either SomeException a))
-> Async a
-> Eff es (Either SomeException a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Async a -> IO (Either SomeException a)
forall a. Async a -> IO (Either SomeException a)
A.waitCatch

-- | Lifted 'A.waitAny'.
waitAny :: Concurrent :> es => [Async a] -> Eff es (Async a, a)
waitAny :: [Async a] -> Eff es (Async a, a)
waitAny = IO (Async a, a) -> Eff es (Async a, a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (Async a, a) -> Eff es (Async a, a))
-> ([Async a] -> IO (Async a, a))
-> [Async a]
-> Eff es (Async a, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Async a] -> IO (Async a, a)
forall a. [Async a] -> IO (Async a, a)
A.waitAny

-- | Lifted 'A.waitAnyCatch'.
waitAnyCatch
  :: Concurrent :> es
  => [Async a]
  -> Eff es (Async a, Either SomeException a)
waitAnyCatch :: [Async a] -> Eff es (Async a, Either SomeException a)
waitAnyCatch = IO (Async a, Either SomeException a)
-> Eff es (Async a, Either SomeException a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (Async a, Either SomeException a)
 -> Eff es (Async a, Either SomeException a))
-> ([Async a] -> IO (Async a, Either SomeException a))
-> [Async a]
-> Eff es (Async a, Either SomeException a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Async a] -> IO (Async a, Either SomeException a)
forall a. [Async a] -> IO (Async a, Either SomeException a)
A.waitAnyCatch

-- | Lifted 'A.waitAnyCancel'.
waitAnyCancel :: Concurrent :> es => [Async a] -> Eff es (Async a, a)
waitAnyCancel :: [Async a] -> Eff es (Async a, a)
waitAnyCancel = IO (Async a, a) -> Eff es (Async a, a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (Async a, a) -> Eff es (Async a, a))
-> ([Async a] -> IO (Async a, a))
-> [Async a]
-> Eff es (Async a, a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Async a] -> IO (Async a, a)
forall a. [Async a] -> IO (Async a, a)
A.waitAnyCancel

-- | Lifted 'A.waitAnyCatchCancel'.
waitAnyCatchCancel
  :: Concurrent :> es
  => [Async a]
  -> Eff es (Async a, Either SomeException a)
waitAnyCatchCancel :: [Async a] -> Eff es (Async a, Either SomeException a)
waitAnyCatchCancel = IO (Async a, Either SomeException a)
-> Eff es (Async a, Either SomeException a)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (Async a, Either SomeException a)
 -> Eff es (Async a, Either SomeException a))
-> ([Async a] -> IO (Async a, Either SomeException a))
-> [Async a]
-> Eff es (Async a, Either SomeException a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Async a] -> IO (Async a, Either SomeException a)
forall a. [Async a] -> IO (Async a, Either SomeException a)
A.waitAnyCatchCancel

-- | Lifted 'A.waitEither'.
waitEither
  :: Concurrent :> es
  => Async a
  -> Async b
  -> Eff es (Either a b)
waitEither :: Async a -> Async b -> Eff es (Either a b)
waitEither Async a
a Async b
b = IO (Either a b) -> Eff es (Either a b)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (Either a b) -> Eff es (Either a b))
-> IO (Either a b) -> Eff es (Either a b)
forall a b. (a -> b) -> a -> b
$ Async a -> Async b -> IO (Either a b)
forall a b. Async a -> Async b -> IO (Either a b)
A.waitEither Async a
a Async b
b

-- | Lifted 'A.waitEitherCatch'.
waitEitherCatch
  :: Concurrent :> es
  => Async a
  -> Async b
  -> Eff es (Either (Either SomeException a) (Either SomeException b))
waitEitherCatch :: Async a
-> Async b
-> Eff
     es (Either (Either SomeException a) (Either SomeException b))
waitEitherCatch Async a
a Async b
b = IO (Either (Either SomeException a) (Either SomeException b))
-> Eff
     es (Either (Either SomeException a) (Either SomeException b))
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (Either (Either SomeException a) (Either SomeException b))
 -> Eff
      es (Either (Either SomeException a) (Either SomeException b)))
-> IO (Either (Either SomeException a) (Either SomeException b))
-> Eff
     es (Either (Either SomeException a) (Either SomeException b))
forall a b. (a -> b) -> a -> b
$ Async a
-> Async b
-> IO (Either (Either SomeException a) (Either SomeException b))
forall a b.
Async a
-> Async b
-> IO (Either (Either SomeException a) (Either SomeException b))
A.waitEitherCatch Async a
a Async b
b

-- | Lifted 'A.waitEitherCancel'.
waitEitherCancel
  :: Concurrent :> es
  => Async a
  -> Async b
  -> Eff es (Either a b)
waitEitherCancel :: Async a -> Async b -> Eff es (Either a b)
waitEitherCancel Async a
a Async b
b = IO (Either a b) -> Eff es (Either a b)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (Either a b) -> Eff es (Either a b))
-> IO (Either a b) -> Eff es (Either a b)
forall a b. (a -> b) -> a -> b
$ Async a -> Async b -> IO (Either a b)
forall a b. Async a -> Async b -> IO (Either a b)
A.waitEitherCancel Async a
a Async b
b

-- | Lifted 'A.waitEitherCatchCancel'.
waitEitherCatchCancel
  :: Concurrent :> es
  => Async a
  -> Async b
  -> Eff es (Either (Either SomeException a) (Either SomeException b))
waitEitherCatchCancel :: Async a
-> Async b
-> Eff
     es (Either (Either SomeException a) (Either SomeException b))
waitEitherCatchCancel Async a
a Async b
b = IO (Either (Either SomeException a) (Either SomeException b))
-> Eff
     es (Either (Either SomeException a) (Either SomeException b))
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_  (IO (Either (Either SomeException a) (Either SomeException b))
 -> Eff
      es (Either (Either SomeException a) (Either SomeException b)))
-> IO (Either (Either SomeException a) (Either SomeException b))
-> Eff
     es (Either (Either SomeException a) (Either SomeException b))
forall a b. (a -> b) -> a -> b
$ Async a
-> Async b
-> IO (Either (Either SomeException a) (Either SomeException b))
forall a b.
Async a
-> Async b
-> IO (Either (Either SomeException a) (Either SomeException b))
A.waitEitherCatch Async a
a Async b
b

-- | Lifted 'A.waitEither_'.
waitEither_ :: Concurrent :> es => Async a -> Async b -> Eff es ()
waitEither_ :: Async a -> Async b -> Eff es ()
waitEither_ Async a
a Async b
b = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> IO () -> Eff es ()
forall a b. (a -> b) -> a -> b
$ Async a -> Async b -> IO ()
forall a b. Async a -> Async b -> IO ()
A.waitEither_ Async a
a Async b
b

-- | Lifted 'A.waitBoth'.
waitBoth :: Concurrent :> es => Async a -> Async b -> Eff es (a, b)
waitBoth :: Async a -> Async b -> Eff es (a, b)
waitBoth Async a
a Async b
b = IO (a, b) -> Eff es (a, b)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (a, b) -> Eff es (a, b)) -> IO (a, b) -> Eff es (a, b)
forall a b. (a -> b) -> a -> b
$ Async a -> Async b -> IO (a, b)
forall a b. Async a -> Async b -> IO (a, b)
A.waitBoth Async a
a Async b
b

-- | Lifted 'A.link'.
link :: Concurrent :> es => Async a -> Eff es ()
link :: Async a -> Eff es ()
link = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (Async a -> IO ()) -> Async a -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Async a -> IO ()
forall a. Async a -> IO ()
A.link

-- | Lifted 'A.linkOnly'.
linkOnly :: Concurrent :> es => (SomeException -> Bool) -> Async a -> Eff es ()
linkOnly :: (SomeException -> Bool) -> Async a -> Eff es ()
linkOnly SomeException -> Bool
f = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (Async a -> IO ()) -> Async a -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SomeException -> Bool) -> Async a -> IO ()
forall a. (SomeException -> Bool) -> Async a -> IO ()
A.linkOnly SomeException -> Bool
f

-- | Lifted 'A.link2'.
link2 :: Concurrent :> es => Async a -> Async b -> Eff es ()
link2 :: Async a -> Async b -> Eff es ()
link2 Async a
a Async b
b = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> IO () -> Eff es ()
forall a b. (a -> b) -> a -> b
$ Async a -> Async b -> IO ()
forall a b. Async a -> Async b -> IO ()
A.link2 Async a
a Async b
b

-- | Lifted 'A.link2Only'.
link2Only :: Concurrent :> es => (SomeException -> Bool) -> Async a -> Async b -> Eff es ()
link2Only :: (SomeException -> Bool) -> Async a -> Async b -> Eff es ()
link2Only SomeException -> Bool
f Async a
a Async b
b = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> IO () -> Eff es ()
forall a b. (a -> b) -> a -> b
$ (SomeException -> Bool) -> Async a -> Async b -> IO ()
forall a b. (SomeException -> Bool) -> Async a -> Async b -> IO ()
A.link2Only SomeException -> Bool
f Async a
a Async b
b

-- | Lifted 'A.race'.
race :: Concurrent :> es => Eff es a -> Eff es b -> Eff es (Either a b)
race :: Eff es a -> Eff es b -> Eff es (Either a b)
race Eff es a
ma Eff es b
mb = (Env es -> IO (Either a b)) -> Eff es (Either a b)
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (Either a b)) -> Eff es (Either a b))
-> (Env es -> IO (Either a b)) -> Eff es (Either a b)
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  IO a -> IO b -> IO (Either a b)
forall a b. IO a -> IO b -> IO (Either a b)
A.race (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
ma (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) (Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es b
mb (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'A.race_'.
race_ ::  Concurrent :> es => Eff es a -> Eff es b -> Eff es ()
race_ :: Eff es a -> Eff es b -> Eff es ()
race_ Eff es a
ma Eff es b
mb = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  IO a -> IO b -> IO ()
forall a b. IO a -> IO b -> IO ()
A.race_ (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
ma (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) (Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es b
mb (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'A.concurrently'.
concurrently :: Concurrent :> es => Eff es a -> Eff es b -> Eff es (a, b)
concurrently :: Eff es a -> Eff es b -> Eff es (a, b)
concurrently Eff es a
ma Eff es b
mb = (Env es -> IO (a, b)) -> Eff es (a, b)
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (a, b)) -> Eff es (a, b))
-> (Env es -> IO (a, b)) -> Eff es (a, b)
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  IO a -> IO b -> IO (a, b)
forall a b. IO a -> IO b -> IO (a, b)
A.concurrently (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
ma (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) (Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es b
mb (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'A.concurrently_'.
concurrently_ :: Concurrent :> es => Eff es a -> Eff es b -> Eff es ()
concurrently_ :: Eff es a -> Eff es b -> Eff es ()
concurrently_ Eff es a
ma Eff es b
mb = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  IO a -> IO b -> IO ()
forall a b. IO a -> IO b -> IO ()
A.concurrently_ (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
ma (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) (Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es b
mb (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- Below functions use variants from the @unliftio@ library as they minimize the
-- amount of spawned threads and are thus much more efficient than the ones from
-- the @async@ library.

-- | Lifted 'A.mapConcurrently'.
mapConcurrently
  :: (Traversable f, Concurrent :> es)
  => (a -> Eff es b)
  -> f a
  -> Eff es (f b)
mapConcurrently :: (a -> Eff es b) -> f a -> Eff es (f b)
mapConcurrently a -> Eff es b
f f a
t = (Env es -> IO (f b)) -> Eff es (f b)
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (f b)) -> Eff es (f b))
-> (Env es -> IO (f b)) -> Eff es (f b)
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  (a -> IO b) -> f a -> IO (f b)
forall (m :: Type -> Type) (t :: Type -> Type) a b.
(MonadUnliftIO m, Traversable t) =>
(a -> m b) -> t a -> m (t b)
U.mapConcurrently (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) f a
t

-- | Lifted 'A.mapConcurrently_'.
mapConcurrently_
  :: (Foldable f, Concurrent :> es)
  => (a -> Eff es b)
  -> f a
  -> Eff es ()
mapConcurrently_ :: (a -> Eff es b) -> f a -> Eff es ()
mapConcurrently_ a -> Eff es b
f f a
t = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  (a -> IO b) -> f a -> IO ()
forall (m :: Type -> Type) (f :: Type -> Type) a b.
(MonadUnliftIO m, Foldable f) =>
(a -> m b) -> f a -> m ()
U.mapConcurrently_ (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) f a
t

-- | Lifted 'A.forConcurrently'.
forConcurrently
  :: (Traversable f, Concurrent :> es)
  => f a
  -> (a -> Eff es b)
  -> Eff es (f b)
forConcurrently :: f a -> (a -> Eff es b) -> Eff es (f b)
forConcurrently f a
t a -> Eff es b
f = (Env es -> IO (f b)) -> Eff es (f b)
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (f b)) -> Eff es (f b))
-> (Env es -> IO (f b)) -> Eff es (f b)
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  f a -> (a -> IO b) -> IO (f b)
forall (m :: Type -> Type) (t :: Type -> Type) a b.
(MonadUnliftIO m, Traversable t) =>
t a -> (a -> m b) -> m (t b)
U.forConcurrently f a
t (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'A.forConcurrently_'.
forConcurrently_
  :: (Foldable f, Concurrent :> es)
  => f a
  -> (a -> Eff es b)
  -> Eff es ()
forConcurrently_ :: f a -> (a -> Eff es b) -> Eff es ()
forConcurrently_ f a
t a -> Eff es b
f = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  f a -> (a -> IO b) -> IO ()
forall (m :: Type -> Type) (f :: Type -> Type) a b.
(MonadUnliftIO m, Foldable f) =>
f a -> (a -> m b) -> m ()
U.forConcurrently_ f a
t (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'A.replicateConcurrently'.
replicateConcurrently :: Concurrent :> es => Int -> Eff es a -> Eff es [a]
replicateConcurrently :: Int -> Eff es a -> Eff es [a]
replicateConcurrently Int
n Eff es a
f = (Env es -> IO [a]) -> Eff es [a]
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO [a]) -> Eff es [a])
-> (Env es -> IO [a]) -> Eff es [a]
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Int -> IO a -> IO [a]
forall (m :: Type -> Type) b.
MonadUnliftIO m =>
Int -> m b -> m [b]
U.replicateConcurrently Int
n (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'A.replicateConcurrently_'.
replicateConcurrently_ :: Concurrent :> es => Int -> Eff es a -> Eff es ()
replicateConcurrently_ :: Int -> Eff es a -> Eff es ()
replicateConcurrently_ Int
n Eff es a
f = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Int -> IO a -> IO ()
forall (m :: Type -> Type) a.
(Applicative m, MonadUnliftIO m) =>
Int -> m a -> m ()
U.replicateConcurrently_ Int
n (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

----------------------------------------
-- Pooled concurrency (unliftio)

-- | Lifted 'U.pooledMapConcurrentlyN'.
pooledMapConcurrentlyN
  :: (Concurrent :> es, Traversable t)
  => Int
  -> (a -> Eff es b)
  -> t a
  -> Eff es (t b)
pooledMapConcurrentlyN :: Int -> (a -> Eff es b) -> t a -> Eff es (t b)
pooledMapConcurrentlyN  Int
threads a -> Eff es b
f t a
t = (Env es -> IO (t b)) -> Eff es (t b)
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (t b)) -> Eff es (t b))
-> (Env es -> IO (t b)) -> Eff es (t b)
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Int -> (a -> IO b) -> t a -> IO (t b)
forall (m :: Type -> Type) (t :: Type -> Type) a b.
(MonadUnliftIO m, Traversable t) =>
Int -> (a -> m b) -> t a -> m (t b)
U.pooledMapConcurrentlyN Int
threads (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) t a
t

-- | Lifted 'U.pooledMapConcurrently'.
pooledMapConcurrently
  :: (Concurrent :> es, Traversable t)
  => (a -> Eff es b)
  -> t a
  -> Eff es (t b)
pooledMapConcurrently :: (a -> Eff es b) -> t a -> Eff es (t b)
pooledMapConcurrently a -> Eff es b
f t a
t = (Env es -> IO (t b)) -> Eff es (t b)
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (t b)) -> Eff es (t b))
-> (Env es -> IO (t b)) -> Eff es (t b)
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  (a -> IO b) -> t a -> IO (t b)
forall (m :: Type -> Type) (t :: Type -> Type) a b.
(MonadUnliftIO m, Traversable t) =>
(a -> m b) -> t a -> m (t b)
U.pooledMapConcurrently (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) t a
t

-- | Lifted 'U.pooledMapConcurrentlyN'.
pooledMapConcurrentlyN_
  :: (Concurrent :> es, Foldable f)
  => Int
  -> (a -> Eff es b)
  -> f a
  -> Eff es ()
pooledMapConcurrentlyN_ :: Int -> (a -> Eff es b) -> f a -> Eff es ()
pooledMapConcurrentlyN_  Int
threads a -> Eff es b
f f a
t = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Int -> (a -> IO b) -> f a -> IO ()
forall (m :: Type -> Type) (f :: Type -> Type) a b.
(MonadUnliftIO m, Foldable f) =>
Int -> (a -> m b) -> f a -> m ()
U.pooledMapConcurrentlyN_ Int
threads (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) f a
t

-- | Lifted 'U.pooledMapConcurrently_'.
pooledMapConcurrently_
  :: (Concurrent :> es, Foldable f)
  => (a -> Eff es b)
  -> f a
  -> Eff es ()
pooledMapConcurrently_ :: (a -> Eff es b) -> f a -> Eff es ()
pooledMapConcurrently_ a -> Eff es b
f f a
t = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  (a -> IO b) -> f a -> IO ()
forall (m :: Type -> Type) (f :: Type -> Type) a b.
(MonadUnliftIO m, Foldable f) =>
(a -> m b) -> f a -> m ()
U.pooledMapConcurrently_ (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) f a
t

-- | Lifted 'U.pooledForConcurrentlyN'.
pooledForConcurrentlyN
  :: (Concurrent :> es, Traversable t)
  => Int
  -> t a
  -> (a -> Eff es b)
  -> Eff es (t b)
pooledForConcurrentlyN :: Int -> t a -> (a -> Eff es b) -> Eff es (t b)
pooledForConcurrentlyN  Int
threads t a
t a -> Eff es b
f = (Env es -> IO (t b)) -> Eff es (t b)
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (t b)) -> Eff es (t b))
-> (Env es -> IO (t b)) -> Eff es (t b)
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Int -> t a -> (a -> IO b) -> IO (t b)
forall (m :: Type -> Type) (t :: Type -> Type) a b.
(MonadUnliftIO m, Traversable t) =>
Int -> t a -> (a -> m b) -> m (t b)
U.pooledForConcurrentlyN Int
threads t a
t (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'U.pooledForConcurrently'.
pooledForConcurrently
  :: (Concurrent :> es, Traversable t)
  => t a
  -> (a -> Eff es b)
  -> Eff es (t b)
pooledForConcurrently :: t a -> (a -> Eff es b) -> Eff es (t b)
pooledForConcurrently t a
t a -> Eff es b
f = (Env es -> IO (t b)) -> Eff es (t b)
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (t b)) -> Eff es (t b))
-> (Env es -> IO (t b)) -> Eff es (t b)
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  t a -> (a -> IO b) -> IO (t b)
forall (m :: Type -> Type) (t :: Type -> Type) a b.
(MonadUnliftIO m, Traversable t) =>
t a -> (a -> m b) -> m (t b)
U.pooledForConcurrently t a
t (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'U.pooledForConcurrentlyN'.
pooledForConcurrentlyN_
  :: (Concurrent :> es, Foldable f)
  => Int
  -> f a
  -> (a -> Eff es b)
  -> Eff es ()
pooledForConcurrentlyN_ :: Int -> f a -> (a -> Eff es b) -> Eff es ()
pooledForConcurrentlyN_  Int
threads f a
t a -> Eff es b
f = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Int -> f a -> (a -> IO b) -> IO ()
forall (m :: Type -> Type) (t :: Type -> Type) a b.
(MonadUnliftIO m, Foldable t) =>
Int -> t a -> (a -> m b) -> m ()
U.pooledForConcurrentlyN_ Int
threads f a
t (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'U.pooledForConcurrently_'.
pooledForConcurrently_
  :: (Concurrent :> es, Foldable f)
  => f a
  -> (a -> Eff es b)
  -> Eff es ()
pooledForConcurrently_ :: f a -> (a -> Eff es b) -> Eff es ()
pooledForConcurrently_ f a
t a -> Eff es b
f = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  f a -> (a -> IO b) -> IO ()
forall (m :: Type -> Type) (f :: Type -> Type) a b.
(MonadUnliftIO m, Foldable f) =>
f a -> (a -> m b) -> m ()
U.pooledForConcurrently_ f a
t (\a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) (Env es -> IO b) -> IO (Env es) -> IO b
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'U.pooledReplicateConcurrentlyN'.
pooledReplicateConcurrentlyN :: Concurrent :> es => Int -> Int -> Eff es a -> Eff es [a]
pooledReplicateConcurrentlyN :: Int -> Int -> Eff es a -> Eff es [a]
pooledReplicateConcurrentlyN Int
threads Int
n Eff es a
f = (Env es -> IO [a]) -> Eff es [a]
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO [a]) -> Eff es [a])
-> (Env es -> IO [a]) -> Eff es [a]
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Int -> Int -> IO a -> IO [a]
forall (m :: Type -> Type) a.
MonadUnliftIO m =>
Int -> Int -> m a -> m [a]
U.pooledReplicateConcurrentlyN Int
threads Int
n (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'U.pooledReplicateConcurrently'.
pooledReplicateConcurrently :: Concurrent :> es => Int -> Eff es a -> Eff es [a]
pooledReplicateConcurrently :: Int -> Eff es a -> Eff es [a]
pooledReplicateConcurrently Int
n Eff es a
f = (Env es -> IO [a]) -> Eff es [a]
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO [a]) -> Eff es [a])
-> (Env es -> IO [a]) -> Eff es [a]
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Int -> IO a -> IO [a]
forall (m :: Type -> Type) b.
MonadUnliftIO m =>
Int -> m b -> m [b]
U.pooledReplicateConcurrently Int
n (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'U.pooledReplicateConcurrentlyN_'.
pooledReplicateConcurrentlyN_ :: Concurrent :> es => Int -> Int -> Eff es a -> Eff es ()
pooledReplicateConcurrentlyN_ :: Int -> Int -> Eff es a -> Eff es ()
pooledReplicateConcurrentlyN_ Int
threads Int
n Eff es a
f = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Int -> Int -> IO a -> IO ()
forall (m :: Type -> Type) a.
MonadUnliftIO m =>
Int -> Int -> m a -> m ()
U.pooledReplicateConcurrentlyN_ Int
threads Int
n (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

-- | Lifted 'U.pooledReplicateConcurrently_'.
pooledReplicateConcurrently_ :: Concurrent :> es => Int -> Eff es a -> Eff es ()
pooledReplicateConcurrently_ :: Int -> Eff es a -> Eff es ()
pooledReplicateConcurrently_ Int
n Eff es a
f = (Env es -> IO ()) -> Eff es ()
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO ()) -> Eff es ()) -> (Env es -> IO ()) -> Eff es ()
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Int -> IO a -> IO ()
forall (m :: Type -> Type) a. MonadUnliftIO m => Int -> m a -> m ()
U.pooledReplicateConcurrently_ Int
n (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es)

----------------------------------------
-- Conc

-- | Lifted 'U.Conc'.
data Conc :: [Effect] -> Type -> Type where
  Action :: Eff es a -> Conc es a
  Apply  :: Conc es (v -> a) -> Conc es v -> Conc es a
  LiftA2 :: (x -> y -> a) -> Conc es x -> Conc es y -> Conc es a
  Pure   :: a -> Conc es a
  Alt    :: Conc es a -> Conc es a -> Conc es a
  Empty  :: Conc es a

deriving instance Functor (Conc es)

instance Applicative (Conc es) where
  pure :: a -> Conc es a
pure   = a -> Conc es a
forall a (es :: [Effect]). a -> Conc es a
Pure
  <*> :: Conc es (a -> b) -> Conc es a -> Conc es b
(<*>)  = Conc es (a -> b) -> Conc es a -> Conc es b
forall (es :: [Effect]) a b.
Conc es (a -> b) -> Conc es a -> Conc es b
Apply
  <* :: Conc es a -> Conc es b -> Conc es a
(<*)   = (a -> b -> a) -> Conc es a -> Conc es b -> Conc es a
forall x y a (es :: [Effect]).
(x -> y -> a) -> Conc es x -> Conc es y -> Conc es a
LiftA2 (\a
x b
_ -> a
x)
  *> :: Conc es a -> Conc es b -> Conc es b
(*>)   = (a -> b -> b) -> Conc es a -> Conc es b -> Conc es b
forall x y a (es :: [Effect]).
(x -> y -> a) -> Conc es x -> Conc es y -> Conc es a
LiftA2 (\a
_ b
y -> b
y)
  liftA2 :: (a -> b -> c) -> Conc es a -> Conc es b -> Conc es c
liftA2 = (a -> b -> c) -> Conc es a -> Conc es b -> Conc es c
forall x y a (es :: [Effect]).
(x -> y -> a) -> Conc es x -> Conc es y -> Conc es a
LiftA2

instance Alternative (Conc es) where
  empty :: Conc es a
empty = Conc es a
forall (es :: [Effect]) a. Conc es a
Empty
  <|> :: Conc es a -> Conc es a -> Conc es a
(<|>) = Conc es a -> Conc es a -> Conc es a
forall (es :: [Effect]) a. Conc es a -> Conc es a -> Conc es a
Alt

instance Semigroup a => Semigroup (Conc es a) where
  <> :: Conc es a -> Conc es a -> Conc es a
(<>) = (a -> a -> a) -> Conc es a -> Conc es a -> Conc es a
forall (f :: Type -> Type) 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 (Conc es a) where
  mempty :: Conc es a
mempty = a -> Conc es a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure a
forall a. Monoid a => a
mempty

-- | Lifted 'U.conc'.
conc :: Eff es a -> Conc es a
conc :: Eff es a -> Conc es a
conc = Eff es a -> Conc es a
forall (es :: [Effect]) a. Eff es a -> Conc es a
Action

-- | Lifted 'U.runConc'.
runConc :: Concurrent :> es => Conc es a -> Eff es a
runConc :: Conc es a -> Eff es a
runConc Conc es a
m = (Env es -> IO a) -> Eff es a
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO a) -> Eff es a) -> (Env es -> IO a) -> Eff es a
forall a b. (a -> b) -> a -> b
$ \Env es
es -> Conc IO a -> IO a
forall (m :: Type -> Type) a. MonadUnliftIO m => Conc m a -> m a
U.runConc (Env es -> Conc es a -> Conc IO a
forall (es :: [Effect]) a. Env es -> Conc es a -> Conc IO a
unliftConc Env es
es Conc es a
m)
  where
    unliftConc :: Env es -> Conc es a -> U.Conc IO a
    unliftConc :: Env es -> Conc es a -> Conc IO a
unliftConc Env es
es = \case
      Action Eff es a
f     -> IO a -> Conc IO a
forall (m :: Type -> Type) a. m a -> Conc m a
I.Action (IO a -> Conc IO a) -> IO a -> Conc IO a
forall a b. (a -> b) -> a -> b
$ Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f (Env es -> IO a) -> IO (Env es) -> IO a
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es
      Apply Conc es (v -> a)
a Conc es v
b    -> Conc IO (v -> a) -> Conc IO v -> Conc IO a
forall (m :: Type -> Type) v a.
Conc m (v -> a) -> Conc m v -> Conc m a
I.Apply (Env es -> Conc es (v -> a) -> Conc IO (v -> a)
forall (es :: [Effect]) a. Env es -> Conc es a -> Conc IO a
unliftConc Env es
es Conc es (v -> a)
a) (Env es -> Conc es v -> Conc IO v
forall (es :: [Effect]) a. Env es -> Conc es a -> Conc IO a
unliftConc Env es
es Conc es v
b)
      LiftA2 x -> y -> a
f Conc es x
a Conc es y
b -> (x -> y -> a) -> Conc IO x -> Conc IO y -> Conc IO a
forall x y a (m :: Type -> Type).
(x -> y -> a) -> Conc m x -> Conc m y -> Conc m a
I.LiftA2 x -> y -> a
f (Env es -> Conc es x -> Conc IO x
forall (es :: [Effect]) a. Env es -> Conc es a -> Conc IO a
unliftConc Env es
es Conc es x
a) (Env es -> Conc es y -> Conc IO y
forall (es :: [Effect]) a. Env es -> Conc es a -> Conc IO a
unliftConc Env es
es Conc es y
b)
      Pure a
a       -> a -> Conc IO a
forall a (m :: Type -> Type). a -> Conc m a
I.Pure a
a
      Alt Conc es a
a Conc es a
b      -> Conc IO a -> Conc IO a -> Conc IO a
forall (m :: Type -> Type) a. Conc m a -> Conc m a -> Conc m a
I.Alt (Env es -> Conc es a -> Conc IO a
forall (es :: [Effect]) a. Env es -> Conc es a -> Conc IO a
unliftConc Env es
es Conc es a
a) (Env es -> Conc es a -> Conc IO a
forall (es :: [Effect]) a. Env es -> Conc es a -> Conc IO a
unliftConc Env es
es Conc es a
b)
      Conc es a
Empty        -> Conc IO a
forall (m :: Type -> Type) a. Conc m a
I.Empty

----------------------------------------
-- Concurrently

-- | Lifted 'A.Concurrently'.
newtype Concurrently es a = Concurrently { Concurrently es a -> Eff es a
runConcurrently :: Eff es a }

instance Functor (Concurrently es) where
  fmap :: (a -> b) -> Concurrently es a -> Concurrently es b
fmap a -> b
f (Concurrently Eff es a
a) = Eff es b -> Concurrently es b
forall (es :: [Effect]) a. Eff es a -> Concurrently es a
Concurrently ((a -> b) -> Eff es a -> Eff es b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Eff es a
a)

instance Concurrent :> es => Applicative (Concurrently es) where
  pure :: a -> Concurrently es a
pure = Eff es a -> Concurrently es a
forall (es :: [Effect]) a. Eff es a -> Concurrently es a
Concurrently (Eff es a -> Concurrently es a)
-> (a -> Eff es a) -> a -> Concurrently es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Eff es a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure
  Concurrently Eff es (a -> b)
fs <*> :: Concurrently es (a -> b) -> Concurrently es a -> Concurrently es b
<*> Concurrently Eff es a
as =
    Eff es b -> Concurrently es b
forall (es :: [Effect]) a. Eff es a -> Concurrently es a
Concurrently ((\(a -> b
f, a
a) -> a -> b
f a
a) ((a -> b, a) -> b) -> Eff es (a -> b, a) -> Eff es b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Eff es (a -> b) -> Eff es a -> Eff es (a -> b, a)
forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Eff es a -> Eff es b -> Eff es (a, b)
concurrently Eff es (a -> b)
fs Eff es a
as)

instance Concurrent :> es => Alternative (Concurrently es) where
  empty :: Concurrently es a
empty = Eff es a -> Concurrently es a
forall (es :: [Effect]) a. Eff es a -> Concurrently es a
Concurrently (Eff es a -> Concurrently es a)
-> (IO () -> Eff es a) -> IO () -> Concurrently es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> Eff es a
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO a -> Eff es a) -> (IO () -> IO a) -> IO () -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO () -> IO a
forall (f :: Type -> Type) a b. Applicative f => f a -> f b
forever (IO () -> Concurrently es a) -> IO () -> Concurrently es a
forall a b. (a -> b) -> a -> b
$ Int -> IO ()
threadDelay Int
forall a. Bounded a => a
maxBound
  Concurrently Eff es a
as <|> :: Concurrently es a -> Concurrently es a -> Concurrently es a
<|> Concurrently Eff es a
bs =
    Eff es a -> Concurrently es a
forall (es :: [Effect]) a. Eff es a -> Concurrently es a
Concurrently ((a -> a) -> (a -> a) -> Either a a -> a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either a -> a
forall a. a -> a
id a -> a
forall a. a -> a
id (Either a a -> a) -> Eff es (Either a a) -> Eff es a
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Eff es a -> Eff es a -> Eff es (Either a a)
forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Eff es a -> Eff es b -> Eff es (Either a b)
race Eff es a
as Eff es a
bs)

instance (Concurrent :> es, Semigroup a) => Semigroup (Concurrently es a) where
  <> :: Concurrently es a -> Concurrently es a -> Concurrently es a
(<>) = (a -> a -> a)
-> Concurrently es a -> Concurrently es a -> Concurrently es a
forall (f :: Type -> Type) 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 (Concurrent :> es, Monoid a) => Monoid (Concurrently es a) where
  mempty :: Concurrently es a
mempty = a -> Concurrently es a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure a
forall a. Monoid a => a
mempty

----------------------------------------
-- Helpers

liftAsync
  :: (IO a -> IO (Async a))
  -> Eff es a
  -> Eff es (Async a)
liftAsync :: (IO a -> IO (Async a)) -> Eff es a -> Eff es (Async a)
liftAsync IO a -> IO (Async a)
fork Eff es a
action = (Env es -> IO (Async a)) -> Eff es (Async a)
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (Async a)) -> Eff es (Async a))
-> (Env es -> IO (Async a)) -> Eff es (Async a)
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Env es
esA <- Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es
  IO a -> IO (Async a)
fork (IO a -> IO (Async a)) -> IO a -> IO (Async a)
forall a b. (a -> b) -> a -> b
$ Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
action Env es
esA

liftAsyncWithUnmask
  :: (((forall b. IO b -> IO b) -> IO a) -> IO (Async a))
  -> ((forall b. Eff es b -> Eff es b) -> Eff es a)
  -> Eff es (Async a)
liftAsyncWithUnmask :: (((forall b. IO b -> IO b) -> IO a) -> IO (Async a))
-> ((forall b. Eff es b -> Eff es b) -> Eff es a)
-> Eff es (Async a)
liftAsyncWithUnmask ((forall b. IO b -> IO b) -> IO a) -> IO (Async a)
fork (forall b. Eff es b -> Eff es b) -> Eff es a
action = (Env es -> IO (Async a)) -> Eff es (Async a)
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO (Async a)) -> Eff es (Async a))
-> (Env es -> IO (Async a)) -> Eff es (Async a)
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Env es
esA <- Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es
  -- Unmask never runs its argument in a different thread.
  ((forall b. IO b -> IO b) -> IO a) -> IO (Async a)
fork (((forall b. IO b -> IO b) -> IO a) -> IO (Async a))
-> ((forall b. IO b -> IO b) -> IO a) -> IO (Async a)
forall a b. (a -> b) -> a -> b
$ \forall b. IO b -> IO b
unmask -> Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff ((forall b. Eff es b -> Eff es b) -> Eff es a
action ((forall b. Eff es b -> Eff es b) -> Eff es a)
-> (forall b. Eff es b -> Eff es b) -> Eff es a
forall a b. (a -> b) -> a -> b
$ (IO b -> IO b) -> Eff es b -> Eff es b
forall a b (es :: [Effect]). (IO a -> IO b) -> Eff es a -> Eff es b
reallyUnsafeLiftMapIO IO b -> IO b
forall b. IO b -> IO b
unmask) Env es
esA

liftWithAsync
  :: (IO a -> (Async a -> IO b) -> IO b)
  -> Eff es a
  -> (Async a -> Eff es b)
  -> Eff es b
liftWithAsync :: (IO a -> (Async a -> IO b) -> IO b)
-> Eff es a -> (Async a -> Eff es b) -> Eff es b
liftWithAsync IO a -> (Async a -> IO b) -> IO b
withA Eff es a
action Async a -> Eff es b
k = (Env es -> IO b) -> Eff es b
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO b) -> Eff es b) -> (Env es -> IO b) -> Eff es b
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Env es
esA <- Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es
  IO a -> (Async a -> IO b) -> IO b
withA (Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
action Env es
esA)
        (\Async a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (Async a -> Eff es b
k Async a
a) Env es
es)

liftWithAsyncWithUnmask
  :: (((forall c. IO c -> IO c) -> IO a) -> (Async a -> IO b) -> IO b)
  -> ((forall c. Eff es c -> Eff es c) -> Eff es a)
  -> (Async a -> Eff es b)
  -> Eff es b
liftWithAsyncWithUnmask :: (((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b)
-> ((forall c. Eff es c -> Eff es c) -> Eff es a)
-> (Async a -> Eff es b)
-> Eff es b
liftWithAsyncWithUnmask ((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b
withA (forall c. Eff es c -> Eff es c) -> Eff es a
action Async a -> Eff es b
k = (Env es -> IO b) -> Eff es b
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO b) -> Eff es b) -> (Env es -> IO b) -> Eff es b
forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Env es
esA <- Env es -> IO (Env es)
forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es
  -- Unmask never runs its argument in a different thread.
  ((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b
withA (\forall b. IO b -> IO b
unmask -> Eff es a -> Env es -> IO a
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff ((forall c. Eff es c -> Eff es c) -> Eff es a
action ((forall c. Eff es c -> Eff es c) -> Eff es a)
-> (forall c. Eff es c -> Eff es c) -> Eff es a
forall a b. (a -> b) -> a -> b
$ (IO c -> IO c) -> Eff es c -> Eff es c
forall a b (es :: [Effect]). (IO a -> IO b) -> Eff es a -> Eff es b
reallyUnsafeLiftMapIO IO c -> IO c
forall b. IO b -> IO b
unmask) Env es
esA)
        (\Async a
a -> Eff es b -> Env es -> IO b
forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (Async a -> Eff es b
k Async a
a) Env es
es)