{-# LANGUAGE TemplateHaskell #-} -- | Description: The effect 'Async', providing an interface to "Control.Concurrent.Async" module Polysemy.Async ( -- * Effect Async (..) -- * Actions , async , await , cancel -- * Helpers , sequenceConcurrently -- * Interpretations , asyncToIOFinal ) where import qualified Control.Concurrent.Async as A import Polysemy import Polysemy.Final ------------------------------------------------------------------------------ -- | An effect for spawning asynchronous computations. -- -- The 'Maybe' returned by 'async' is due to the fact that we can't be sure an -- 'Polysemy.Error.Error' effect didn't fail locally. -- -- @since 0.5.0.0 data Async m a where -- | Run the given action asynchronously and return a thread handle. Async :: m a -> Async m (A.Async (Maybe a)) -- | Wait for the thread referenced by the given handle to terminate. Await :: A.Async a -> Async m a -- | Cancel the thread referenced by the given handle. Cancel :: A.Async a -> Async m () makeSem ''Async ------------------------------------------------------------------------------ -- | Perform a sequence of effectful actions concurrently. -- -- @since 1.2.2.0 sequenceConcurrently :: forall t r a. (Traversable t, Member Async r) => t (Sem r a) -> Sem r (t (Maybe a)) sequenceConcurrently t = traverse async t >>= traverse await {-# INLINABLE sequenceConcurrently #-} ------------------------------------------------------------------------------ -- | Run an 'Async' effect in terms of 'A.async' through final 'IO'. -- -- /Beware/: Effects that aren't interpreted in terms of 'IO' -- will have local state semantics in regards to 'Async' effects -- interpreted this way. See 'Final'. -- -- @since 1.2.0.0 asyncToIOFinal :: Member (Final IO) r => Sem (Async ': r) a -> Sem r a asyncToIOFinal = interpretFinal $ \case Async m -> do ins <- getInspectorS m' <- runS m liftS $ A.async (inspect ins <$> m') Await a -> liftS (A.wait a) Cancel a -> liftS (A.cancel a) {-# INLINE asyncToIOFinal #-}