{-# 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 :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Eff es a -> Eff es (Async a)
async = forall a (es :: [Effect]).
(IO a -> IO (Async a)) -> Eff es a -> Eff es (Async a)
liftAsync forall a. IO a -> IO (Async a)
A.async

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

-- | Lifted 'A.asyncOn'.
asyncOn :: Concurrent :> es => Int -> Eff es a -> Eff es (Async a)
asyncOn :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Int -> Eff es a -> Eff es (Async a)
asyncOn Int
cpu = forall a (es :: [Effect]).
(IO a -> IO (Async a)) -> Eff es a -> Eff es (Async a)
liftAsync (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 (es :: [Effect]) a.
(Concurrent :> es) =>
((forall b. Eff es b -> Eff es b) -> Eff es a) -> Eff es (Async a)
asyncWithUnmask = 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 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 :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Int
-> ((forall b. Eff es b -> Eff es b) -> Eff es a)
-> Eff es (Async a)
asyncOnWithUnmask Int
cpu = 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 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Eff es a -> (Async a -> Eff es b) -> Eff es b
withAsync = 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 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Eff es a -> (Async a -> Eff es b) -> Eff es b
withAsyncBound = 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 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Int -> Eff es a -> (Async a -> Eff es b) -> Eff es b
withAsyncOn Int
cpu = 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 (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 (es :: [Effect]) a b.
(Concurrent :> es) =>
((forall c. Eff es c -> Eff es c) -> Eff es a)
-> (Async a -> Eff es b) -> Eff es b
withAsyncWithUnmask = 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 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Int
-> ((forall c. Eff es c -> Eff es c) -> Eff es a)
-> (Async a -> Eff es b)
-> Eff es b
withAsyncOnWithUnmask Int
cpu = 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 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 :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Async a -> Eff es a
wait = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Async a -> IO a
A.wait

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

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

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

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

-- | Lifted 'A.waitAny'.
waitAny :: Concurrent :> es => [Async a] -> Eff es (Async a, a)
waitAny :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
[Async a] -> Eff es (Async a, a)
waitAny = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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 :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
[Async a] -> Eff es (Async a, Either SomeException a)
waitAnyCatch = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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 :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
[Async a] -> Eff es (Async a, a)
waitAnyCancel = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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 :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
[Async a] -> Eff es (Async a, Either SomeException a)
waitAnyCatchCancel = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Async a -> Async b -> Eff es (Either a b)
waitEither Async a
a Async b
b = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Async a
-> Async b
-> Eff
     es (Either (Either SomeException a) (Either SomeException b))
waitEitherCatch Async a
a Async b
b = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> a -> 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Async a -> Async b -> Eff es (Either a b)
waitEitherCancel Async a
a Async b
b = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Async a
-> Async b
-> Eff
     es (Either (Either SomeException a) (Either SomeException b))
waitEitherCatchCancel Async a
a Async b
b = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_  forall a b. (a -> b) -> a -> 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_ :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Async a -> Async b -> Eff es ()
waitEither_ Async a
a Async b
b = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> a -> b
$ 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Async a -> Async b -> Eff es (a, b)
waitBoth Async a
a Async b
b = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> 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 :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Async a -> Eff es ()
link = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Async a -> IO ()
A.link

-- | Lifted 'A.linkOnly'.
linkOnly :: Concurrent :> es => (SomeException -> Bool) -> Async a -> Eff es ()
linkOnly :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
(SomeException -> Bool) -> Async a -> Eff es ()
linkOnly SomeException -> Bool
f = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Async a -> Async b -> Eff es ()
link2 Async a
a Async b
b = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> a -> b
$ 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
(SomeException -> Bool) -> Async a -> Async b -> Eff es ()
link2Only SomeException -> Bool
f Async a
a Async b
b = forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall a b. (a -> b) -> a -> b
$ 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Eff es a -> Eff es b -> Eff es (Either a b)
race Eff es a
ma Eff es b
mb = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall a b. IO a -> IO b -> IO (Either a b)
A.race (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
ma forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es b
mb forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Eff es a -> Eff es b -> Eff es ()
race_ Eff es a
ma Eff es b
mb = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall a b. IO a -> IO b -> IO ()
A.race_ (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
ma forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es b
mb forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Eff es a -> Eff es b -> Eff es (a, b)
concurrently Eff es a
ma Eff es b
mb = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall a b. IO a -> IO b -> IO (a, b)
A.concurrently (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
ma forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es b
mb forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (es :: [Effect]) a b.
(Concurrent :> es) =>
Eff es a -> Eff es b -> Eff es ()
concurrently_ Eff es a
ma Eff es b
mb = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall a b. IO a -> IO b -> IO ()
A.concurrently_ (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
ma forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es) (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es b
mb forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall (f :: Type -> Type) (es :: [Effect]) a b.
(Traversable f, Concurrent :> es) =>
(a -> Eff es b) -> f a -> Eff es (f b)
mapConcurrently a -> Eff es b
f f a
t = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  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 -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (f :: Type -> Type) (es :: [Effect]) a b.
(Foldable f, Concurrent :> es) =>
(a -> Eff es b) -> f a -> Eff es ()
mapConcurrently_ a -> Eff es b
f f a
t = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall (m :: Type -> Type) (f :: Type -> Type) a b.
(MonadUnliftIO m, Foldable f) =>
(a -> m b) -> f a -> m ()
U.mapConcurrently_ (\a
a -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall (f :: Type -> Type) (es :: [Effect]) a b.
(Traversable f, Concurrent :> es) =>
f a -> (a -> Eff es b) -> Eff es (f b)
forConcurrently f a
t a -> Eff es b
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  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 -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (f :: Type -> Type) (es :: [Effect]) a b.
(Foldable f, Concurrent :> es) =>
f a -> (a -> Eff es b) -> Eff es ()
forConcurrently_ f a
t a -> Eff es b
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  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 -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Int -> Eff es a -> Eff es [a]
replicateConcurrently Int
n Eff es a
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall {f :: Type -> Type} {a}.
MonadUnliftIO f =>
Int -> f a -> f [a]
U.replicateConcurrently Int
n (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Int -> Eff es a -> Eff es ()
replicateConcurrently_ Int
n Eff es a
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall (m :: Type -> Type) a.
(Applicative m, MonadUnliftIO m) =>
Int -> m a -> m ()
U.replicateConcurrently_ Int
n (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall (es :: [Effect]) (t :: Type -> Type) a b.
(Concurrent :> es, Traversable t) =>
Int -> (a -> Eff es b) -> t a -> Eff es (t b)
pooledMapConcurrentlyN  Int
threads a -> Eff es b
f t a
t = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  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 -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall (es :: [Effect]) (t :: Type -> Type) a b.
(Concurrent :> es, Traversable t) =>
(a -> Eff es b) -> t a -> Eff es (t b)
pooledMapConcurrently a -> Eff es b
f t a
t = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  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 -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (es :: [Effect]) (f :: Type -> Type) a b.
(Concurrent :> es, Foldable f) =>
Int -> (a -> Eff es b) -> f a -> Eff es ()
pooledMapConcurrentlyN_  Int
threads a -> Eff es b
f f a
t = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  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 -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (es :: [Effect]) (f :: Type -> Type) a b.
(Concurrent :> es, Foldable f) =>
(a -> Eff es b) -> f a -> Eff es ()
pooledMapConcurrently_ a -> Eff es b
f f a
t = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall (m :: Type -> Type) (f :: Type -> Type) a b.
(MonadUnliftIO m, Foldable f) =>
(a -> m b) -> f a -> m ()
U.pooledMapConcurrently_ (\a
a -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall (es :: [Effect]) (t :: Type -> Type) a b.
(Concurrent :> es, Traversable t) =>
Int -> t a -> (a -> Eff es b) -> Eff es (t b)
pooledForConcurrentlyN  Int
threads t a
t a -> Eff es b
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  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 -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall (es :: [Effect]) (t :: Type -> Type) a b.
(Concurrent :> es, Traversable t) =>
t a -> (a -> Eff es b) -> Eff es (t b)
pooledForConcurrently t a
t a -> Eff es b
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  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 -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (es :: [Effect]) (f :: Type -> Type) a b.
(Concurrent :> es, Foldable f) =>
Int -> f a -> (a -> Eff es b) -> Eff es ()
pooledForConcurrentlyN_  Int
threads f a
t a -> Eff es b
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  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 -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (es :: [Effect]) (f :: Type -> Type) a b.
(Concurrent :> es, Foldable f) =>
f a -> (a -> Eff es b) -> Eff es ()
pooledForConcurrently_ f a
t a -> Eff es b
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  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 -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (a -> Eff es b
f a
a) forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Int -> Int -> Eff es a -> Eff es [a]
pooledReplicateConcurrentlyN Int
threads Int
n Eff es a
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall (m :: Type -> Type) a.
MonadUnliftIO m =>
Int -> Int -> m a -> m [a]
U.pooledReplicateConcurrentlyN Int
threads Int
n (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Int -> Eff es a -> Eff es [a]
pooledReplicateConcurrently Int
n Eff es a
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall {f :: Type -> Type} {a}.
MonadUnliftIO f =>
Int -> f a -> f [a]
U.pooledReplicateConcurrently Int
n (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Int -> Int -> Eff es a -> Eff es ()
pooledReplicateConcurrentlyN_ Int
threads Int
n Eff es a
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall (m :: Type -> Type) a.
MonadUnliftIO m =>
Int -> Int -> m a -> m ()
U.pooledReplicateConcurrentlyN_ Int
threads Int
n (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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_ :: forall (es :: [Effect]) a.
(Concurrent :> es) =>
Int -> Eff es a -> Eff es ()
pooledReplicateConcurrently_ Int
n Eff es a
f = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  forall (m :: Type -> Type) a. MonadUnliftIO m => Int -> m a -> m ()
U.pooledReplicateConcurrently_ Int
n (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
f forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< 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 :: forall a. a -> Conc es a
pure   = forall a (es :: [Effect]). a -> Conc es a
Pure
  <*> :: forall a 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
  <* :: forall a b. 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)
  *> :: forall a 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 :: forall a b c. (a -> b -> c) -> Conc es a -> Conc es b -> Conc es c
liftA2 = 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 :: forall a. Conc es a
empty = forall (es :: [Effect]) a. Conc es a
Empty
  <|> :: forall 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
(<>) = forall (f :: Type -> Type) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Semigroup a => a -> a -> a
(<>)

instance Monoid a => Monoid (Conc es a) where
  mempty :: Conc es a
mempty = forall (f :: Type -> Type) a. Applicative f => a -> f a
pure forall a. Monoid a => a
mempty

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

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

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

-- | Lifted 'A.Concurrently'.
newtype Concurrently es a = Concurrently { forall (es :: [Effect]) a. Concurrently es a -> Eff es a
runConcurrently :: Eff es a }

instance Functor (Concurrently es) where
  fmap :: forall a b. (a -> b) -> Concurrently es a -> Concurrently es b
fmap a -> b
f (Concurrently Eff es a
a) = forall (es :: [Effect]) a. Eff es a -> Concurrently es a
Concurrently (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 :: forall a. a -> Concurrently es a
pure = forall (es :: [Effect]) a. Eff es a -> Concurrently es a
Concurrently forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: Type -> Type) a. Applicative f => a -> f a
pure
  Concurrently Eff es (a -> b)
fs <*> :: forall a b.
Concurrently es (a -> b) -> Concurrently es a -> Concurrently es b
<*> Concurrently Eff es a
as =
    forall (es :: [Effect]) a. Eff es a -> Concurrently es a
Concurrently ((\(a -> b
f, a
a) -> a -> b
f a
a) forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> 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 :: forall a. Concurrently es a
empty = forall (es :: [Effect]) a. Eff es a -> Concurrently es a
Concurrently forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: Type -> Type) a b. Applicative f => f a -> f b
forever forall a b. (a -> b) -> a -> b
$ Int -> IO ()
threadDelay forall a. Bounded a => a
maxBound
  Concurrently Eff es a
as <|> :: forall a.
Concurrently es a -> Concurrently es a -> Concurrently es a
<|> Concurrently Eff es a
bs =
    forall (es :: [Effect]) a. Eff es a -> Concurrently es a
Concurrently (forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall a. a -> a
id forall a. a -> a
id forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> 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
(<>) = forall (f :: Type -> Type) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Semigroup a => a -> a -> a
(<>)

instance (Concurrent :> es, Monoid a) => Monoid (Concurrently es a) where
  mempty :: Concurrently es a
mempty = forall (f :: Type -> Type) a. Applicative f => a -> f a
pure forall a. Monoid a => a
mempty

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

liftAsync
  :: (IO a -> IO (Async a))
  -> Eff es a
  -> Eff es (Async a)
liftAsync :: forall a (es :: [Effect]).
(IO a -> IO (Async a)) -> Eff es a -> Eff es (Async a)
liftAsync IO a -> IO (Async a)
fork Eff es a
action = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Env es
esA <- forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es
  IO a -> IO (Async a)
fork forall a b. (a -> b) -> a -> b
$ 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 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)
fork (forall b. Eff es b -> Eff es b) -> Eff es a
action = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Env es
esA <- 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 a b. (a -> b) -> a -> b
$ \forall b. IO b -> IO b
unmask -> 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 a b. (a -> b) -> a -> b
$ forall a b (es :: [Effect]). (IO a -> IO b) -> Eff es a -> Eff es b
reallyUnsafeLiftMapIO 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 :: 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
withA Eff es a
action Async a -> Eff es b
k = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Env es
esA <- forall (es :: [Effect]). Env es -> IO (Env es)
cloneEnv Env es
es
  IO a -> (Async a -> IO b) -> IO b
withA (forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff Eff es a
action Env es
esA)
        (\Async a
a -> 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 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
withA (forall c. Eff es c -> Eff es c) -> Eff es a
action Async a -> Eff es b
k = forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff forall a b. (a -> b) -> a -> b
$ \Env es
es -> do
  Env es
esA <- 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 -> 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 a b. (a -> b) -> a -> b
$ forall a b (es :: [Effect]). (IO a -> IO b) -> Eff es a -> Eff es b
reallyUnsafeLiftMapIO forall b. IO b -> IO b
unmask) Env es
esA)
        (\Async a
a -> forall (es :: [Effect]) a. Eff es a -> Env es -> IO a
unEff (Async a -> Eff es b
k Async a
a) Env es
es)