packages feed

polysemy-conc 0.9.0.0 → 0.10.0.0

raw patch · 34 files changed

+1861/−435 lines, 34 filesdep ~polysemy-resumePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: polysemy-resume

API changes (from Hackage documentation)

- Polysemy.Conc: MonitorResource :: a -> MonitorResource a
- Polysemy.Conc: data EventResource resource
- Polysemy.Conc: newtype MonitorResource a
- Polysemy.Conc: type ChanConsumer e = Scoped (EventChan e) (Consume e)
- Polysemy.Conc: type ChanEvents e = Events (OutChan e) e
- Polysemy.Conc: type EventChan e = EventResource (OutChan e)
- Polysemy.Conc.Effect.Events: EventResource :: resource -> EventResource resource
- Polysemy.Conc.Effect.Events: [$sel:unEventToken:EventResource] :: EventResource resource -> resource
- Polysemy.Conc.Effect.Events: instance GHC.Classes.Eq resource => GHC.Classes.Eq (Polysemy.Conc.Effect.Events.EventResource resource)
- Polysemy.Conc.Effect.Events: instance GHC.Generics.Generic (Polysemy.Conc.Effect.Events.EventResource resource)
- Polysemy.Conc.Effect.Events: instance GHC.Show.Show resource => GHC.Show.Show (Polysemy.Conc.Effect.Events.EventResource resource)
- Polysemy.Conc.Effect.Events: newtype EventResource resource
- Polysemy.Conc.Effect.Monitor: MonitorResource :: a -> MonitorResource a
- Polysemy.Conc.Effect.Monitor: [$sel:unMonitorResource:MonitorResource] :: MonitorResource a -> a
- Polysemy.Conc.Effect.Monitor: newtype MonitorResource a
- Polysemy.Conc.Interpreter.Events: type ChanConsumer e = Scoped (EventChan e) (Consume e)
- Polysemy.Conc.Interpreter.Events: type ChanEvents e = Events (OutChan e) e
- Polysemy.Conc.Interpreter.Events: type EventChan e = EventResource (OutChan e)
- Polysemy.Conc.Interpreter.Mask: Restoration :: (forall a. IO a -> IO a) -> Restoration
- Polysemy.Conc.Interpreter.Mask: [$sel:unRestoration:Restoration] :: Restoration -> forall a. IO a -> IO a
- Polysemy.Conc.Interpreter.Mask: newtype Restoration
- Polysemy.Conc.Sync: data Sync d :: Effect
- Polysemy.Conc.Sync: type ScopedSync res a = Scoped (SyncResources res) (Sync a)
+ Polysemy.Conc: consumeElem :: forall e r. Eq e => Member (Consume e) r => e -> Sem r ()
+ Polysemy.Conc: consumeFind :: forall e r. Member (Consume e) r => (e -> Sem r Bool) -> Sem r e
+ Polysemy.Conc: consumeFirstJust :: forall e a r. Member (Consume e) r => (e -> Sem r (Maybe a)) -> Sem r a
+ Polysemy.Conc: consumeLoop :: Member (Consume e) r => (e -> Sem r ()) -> Sem r ()
+ Polysemy.Conc: consumeWhile :: Member (Consume e) r => (e -> Sem r Bool) -> Sem r ()
+ Polysemy.Conc: data Gate :: Effect
+ Polysemy.Conc: data Lock :: Effect
+ Polysemy.Conc: data Semaphore :: Effect
+ Polysemy.Conc: interpretGate :: forall r. Member (Embed IO) r => InterpreterFor Gate r
+ Polysemy.Conc: interpretGates :: Member (Embed IO) r => InterpreterFor (Scoped_ Gate) r
+ Polysemy.Conc: interpretLockPermissive :: InterpreterFor Lock r
+ Polysemy.Conc: interpretLockReentrant :: Members [Resource, Race, Mask, Embed IO] r => InterpreterFor Lock r
+ Polysemy.Conc: interpretMaskPure :: InterpreterFor Mask r
+ Polysemy.Conc: interpretResumableScoped :: forall param resource effect err r. (forall x. param -> (resource -> Sem r x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc: interpretResumableScopedH :: forall param resource effect err r. (forall x. param -> (resource -> Sem r x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc: interpretResumableScopedWith :: forall extra param resource effect err r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> (resource -> Sem r1 x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r1) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc: interpretResumableScopedWithH :: forall extra param resource effect err r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> (resource -> Sem r1 x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r1) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc: interpretResumableScopedWith_ :: forall extra param effect err r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> Sem r1 x -> Sem r x) -> (forall r0 x. effect (Sem r0) x -> Sem (Stop err : r1) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc: interpretResumableScoped_ :: forall param resource effect err r. (param -> Sem r resource) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc: interpretScopedH' :: forall resource param effect r. (forall e r0 x. param -> (resource -> Tactical e (Sem r0) r x) -> Tactical e (Sem r0) r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical (Scoped param effect) (Sem r0) r x) -> InterpreterFor (Scoped param effect) r
+ Polysemy.Conc: interpretScopedR :: forall param resource effect eo ei r. (forall x. param -> (resource -> Sem (Stop eo : r) x) -> Sem (Stop eo : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop ei : r) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc: interpretScopedRH :: forall param resource effect eo ei r. (forall x. param -> (resource -> Sem (Stop eo : r) x) -> Sem (Stop eo : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop ei : r) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc: interpretScopedRWith :: forall extra param resource effect eo ei r r1. r1 ~ (extra ++ (Stop eo : r)) => r1 ~ ((extra ++ '[Stop eo]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop eo]) => (forall x. param -> (resource -> Sem r1 x) -> Sem (Stop eo : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop ei : r1) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc: interpretScopedRWithH :: forall extra param resource effect eo ei r r1. r1 ~ (extra ++ (Stop eo : r)) => r1 ~ ((extra ++ '[Stop eo]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop eo]) => (forall x. param -> (resource -> Sem r1 x) -> Sem (Stop eo : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop ei : r1) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc: interpretScopedRWith_ :: forall extra param effect eo ei r r1. r1 ~ (extra ++ (Stop eo : r)) => r1 ~ ((extra ++ '[Stop eo]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop eo]) => (forall x. param -> Sem r1 x -> Sem (Stop eo : r) x) -> (forall r0 x. effect (Sem r0) x -> Sem (Stop ei : r1) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc: interpretScopedR_ :: forall param resource effect eo ei r. (param -> Sem (Stop eo : r) resource) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop ei : r) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc: interpretScopedResumable_ :: forall param resource effect err r. (param -> Sem (Stop err : r) resource) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped param effect !! err) r
+ Polysemy.Conc: interpretSemaphoreQ :: Member (Embed IO) r => Int -> InterpreterFor Semaphore r
+ Polysemy.Conc: interpretSemaphoreT :: Member (Embed IO) r => Integer -> InterpreterFor Semaphore r
+ Polysemy.Conc: interpretUninterruptibleMaskPure :: InterpreterFor UninterruptibleMask r
+ Polysemy.Conc: lockOr :: forall r a. Member Lock r => Sem r a -> Sem r a -> Sem r a
+ Polysemy.Conc: lockOrSkip :: forall r a. Member Lock r => Sem r a -> Sem r (Maybe a)
+ Polysemy.Conc: lockOrSkip_ :: forall r a. Member Lock r => Sem r a -> Sem r ()
+ Polysemy.Conc: rescope :: forall param0 param1 effect r. Member (Scoped param1 effect) r => (param0 -> param1) -> InterpreterFor (Scoped param0 effect) r
+ Polysemy.Conc: scoped_ :: forall effect r. Member (Scoped_ effect) r => InterpreterFor effect r
+ Polysemy.Conc: subscribeAsync :: forall e r a. Members [EventConsumer e, Scoped_ Gate, Resource, Race, Async] r => Sem (Consume e : r) () -> Sem r a -> Sem r a
+ Polysemy.Conc: subscribeElem :: forall e r. Eq e => Member (EventConsumer e) r => e -> Sem r ()
+ Polysemy.Conc: subscribeFind :: forall e r. Member (EventConsumer e) r => (e -> Sem (Consume e : r) Bool) -> Sem r e
+ Polysemy.Conc: subscribeFirstJust :: forall e a r. Member (EventConsumer e) r => (e -> Sem (Consume e : r) (Maybe a)) -> Sem r a
+ Polysemy.Conc: subscribeGated :: forall e r. Members [EventConsumer e, Gate] r => InterpreterFor (Consume e) r
+ Polysemy.Conc: subscribeLoopAsync :: forall e r a. Members [EventConsumer e, Gates, Resource, Race, Async] r => (e -> Sem (Consume e : r) ()) -> Sem r a -> Sem r a
+ Polysemy.Conc: subscribeLoopGated :: forall e r. Members [EventConsumer e, Gate] r => (e -> Sem r ()) -> Sem r ()
+ Polysemy.Conc: subscribeWhileAsync :: forall e r a. Members [EventConsumer e, Gates, Resource, Race, Async] r => (e -> Sem (Consume e : r) Bool) -> Sem r a -> Sem r a
+ Polysemy.Conc: subscribeWhileGated :: forall e r. Members [EventConsumer e, Gate] r => (e -> Sem r Bool) -> Sem r ()
+ Polysemy.Conc: timeoutStop :: TimeUnit u => Members [Race, Stop err] r => err -> u -> Sem r a -> Sem r a
+ Polysemy.Conc: type Gates = Scoped_ Gate
+ Polysemy.Conc: type Scoped_ effect = Scoped () effect
+ Polysemy.Conc: withAsyncGated :: forall b r a. Members [Scoped_ Gate, Resource, Race, Async] r => Sem (Gate : r) b -> (Async (Maybe b) -> Sem r a) -> Sem r a
+ Polysemy.Conc: withAsyncGated_ :: forall b r a. Members [Scoped_ Gate, Resource, Race, Async] r => Sem (Gate : r) b -> Sem r a -> Sem r a
+ Polysemy.Conc.Async: withAsyncGated :: forall b r a. Members [Scoped_ Gate, Resource, Race, Async] r => Sem (Gate : r) b -> (Async (Maybe b) -> Sem r a) -> Sem r a
+ Polysemy.Conc.Async: withAsyncGated_ :: forall b r a. Members [Scoped_ Gate, Resource, Race, Async] r => Sem (Gate : r) b -> Sem r a -> Sem r a
+ Polysemy.Conc.Effect.Gate: [Gate] :: Gate m ()
+ Polysemy.Conc.Effect.Gate: [Signal] :: Gate m ()
+ Polysemy.Conc.Effect.Gate: data Gate :: Effect
+ Polysemy.Conc.Effect.Gate: type Gates = Scoped_ Gate
+ Polysemy.Conc.Effect.Gate: withGate :: Member (Scoped_ Gate) r => InterpreterFor Gate r
+ Polysemy.Conc.Effect.Lock: [LockOr] :: m a -> m a -> Lock m a
+ Polysemy.Conc.Effect.Lock: [Lock] :: m a -> Lock m a
+ Polysemy.Conc.Effect.Lock: data Lock :: Effect
+ Polysemy.Conc.Effect.Lock: lock :: forall r a. Member Lock r => Sem r a -> Sem r a
+ Polysemy.Conc.Effect.Lock: lockOr :: forall r a. Member Lock r => Sem r a -> Sem r a -> Sem r a
+ Polysemy.Conc.Effect.Lock: lockOrSkip :: forall r a. Member Lock r => Sem r a -> Sem r (Maybe a)
+ Polysemy.Conc.Effect.Lock: lockOrSkip_ :: forall r a. Member Lock r => Sem r a -> Sem r ()
+ Polysemy.Conc.Effect.Mask: Restoration :: (forall a. IO a -> IO a) -> Restoration
+ Polysemy.Conc.Effect.Mask: [$sel:unRestoration:Restoration] :: Restoration -> forall a. IO a -> IO a
+ Polysemy.Conc.Effect.Mask: newtype Restoration
+ Polysemy.Conc.Effect.Scoped: rescope :: forall param0 param1 effect r. Member (Scoped param1 effect) r => (param0 -> param1) -> InterpreterFor (Scoped param0 effect) r
+ Polysemy.Conc.Effect.Scoped: scoped_ :: forall effect r. Member (Scoped_ effect) r => InterpreterFor effect r
+ Polysemy.Conc.Effect.Scoped: type Scoped_ effect = Scoped () effect
+ Polysemy.Conc.Effect.Semaphore: [Signal] :: Semaphore m ()
+ Polysemy.Conc.Effect.Semaphore: [Wait] :: Semaphore m ()
+ Polysemy.Conc.Effect.Semaphore: data Semaphore :: Effect
+ Polysemy.Conc.Effect.Semaphore: signal :: forall r. Member Semaphore r => Sem r ()
+ Polysemy.Conc.Effect.Semaphore: wait :: forall r. Member Semaphore r => Sem r ()
+ Polysemy.Conc.Events: consumeElem :: forall e r. Eq e => Member (Consume e) r => e -> Sem r ()
+ Polysemy.Conc.Events: consumeFind :: forall e r. Member (Consume e) r => (e -> Sem r Bool) -> Sem r e
+ Polysemy.Conc.Events: consumeFirstJust :: forall e a r. Member (Consume e) r => (e -> Sem r (Maybe a)) -> Sem r a
+ Polysemy.Conc.Events: consumeLoop :: Member (Consume e) r => (e -> Sem r ()) -> Sem r ()
+ Polysemy.Conc.Events: consumeWhile :: Member (Consume e) r => (e -> Sem r Bool) -> Sem r ()
+ Polysemy.Conc.Events: subscribeAsync :: forall e r a. Members [EventConsumer e, Scoped_ Gate, Resource, Race, Async] r => Sem (Consume e : r) () -> Sem r a -> Sem r a
+ Polysemy.Conc.Events: subscribeElem :: forall e r. Eq e => Member (EventConsumer e) r => e -> Sem r ()
+ Polysemy.Conc.Events: subscribeFind :: forall e r. Member (EventConsumer e) r => (e -> Sem (Consume e : r) Bool) -> Sem r e
+ Polysemy.Conc.Events: subscribeFirstJust :: forall e a r. Member (EventConsumer e) r => (e -> Sem (Consume e : r) (Maybe a)) -> Sem r a
+ Polysemy.Conc.Events: subscribeGated :: forall e r. Members [EventConsumer e, Gate] r => InterpreterFor (Consume e) r
+ Polysemy.Conc.Events: subscribeLoopAsync :: forall e r a. Members [EventConsumer e, Gates, Resource, Race, Async] r => (e -> Sem (Consume e : r) ()) -> Sem r a -> Sem r a
+ Polysemy.Conc.Events: subscribeLoopGated :: forall e r. Members [EventConsumer e, Gate] r => (e -> Sem r ()) -> Sem r ()
+ Polysemy.Conc.Events: subscribeWhileAsync :: forall e r a. Members [EventConsumer e, Gates, Resource, Race, Async] r => (e -> Sem (Consume e : r) Bool) -> Sem r a -> Sem r a
+ Polysemy.Conc.Events: subscribeWhileGated :: forall e r. Members [EventConsumer e, Gate] r => (e -> Sem r Bool) -> Sem r ()
+ Polysemy.Conc.Interpreter.Gate: interpretGate :: forall r. Member (Embed IO) r => InterpreterFor Gate r
+ Polysemy.Conc.Interpreter.Gate: interpretGates :: Member (Embed IO) r => InterpreterFor (Scoped_ Gate) r
+ Polysemy.Conc.Interpreter.Lock: interpretLockPermissive :: InterpreterFor Lock r
+ Polysemy.Conc.Interpreter.Lock: interpretLockReentrant :: Members [Resource, Race, Mask, Embed IO] r => InterpreterFor Lock r
+ Polysemy.Conc.Interpreter.Lock: interpretLockReentrantEntered :: Members [Sync (), Resource, Race, Mask, Embed IO] r => ThreadId -> InterpreterFor Lock r
+ Polysemy.Conc.Interpreter.Mask: interpretMaskPure :: InterpreterFor Mask r
+ Polysemy.Conc.Interpreter.Mask: interpretUninterruptibleMaskPure :: InterpreterFor UninterruptibleMask r
+ Polysemy.Conc.Interpreter.Scoped: interpretResumableScoped :: forall param resource effect err r. (forall x. param -> (resource -> Sem r x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc.Interpreter.Scoped: interpretResumableScopedH :: forall param resource effect err r. (forall x. param -> (resource -> Sem r x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc.Interpreter.Scoped: interpretResumableScopedWith :: forall extra param resource effect err r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> (resource -> Sem r1 x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r1) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc.Interpreter.Scoped: interpretResumableScopedWithH :: forall extra param resource effect err r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> (resource -> Sem r1 x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r1) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc.Interpreter.Scoped: interpretResumableScopedWith_ :: forall extra param effect err r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> Sem r1 x -> Sem r x) -> (forall r0 x. effect (Sem r0) x -> Sem (Stop err : r1) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc.Interpreter.Scoped: interpretResumableScoped_ :: forall param resource effect err r. (param -> Sem r resource) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped param (effect !! err)) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedH' :: forall resource param effect r. (forall e r0 x. param -> (resource -> Tactical e (Sem r0) r x) -> Tactical e (Sem r0) r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical (Scoped param effect) (Sem r0) r x) -> InterpreterFor (Scoped param effect) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedR :: forall param resource effect eo ei r. (forall x. param -> (resource -> Sem (Stop eo : r) x) -> Sem (Stop eo : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop ei : r) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedRH :: forall param resource effect eo ei r. (forall x. param -> (resource -> Sem (Stop eo : r) x) -> Sem (Stop eo : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop ei : r) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedRWith :: forall extra param resource effect eo ei r r1. r1 ~ (extra ++ (Stop eo : r)) => r1 ~ ((extra ++ '[Stop eo]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop eo]) => (forall x. param -> (resource -> Sem r1 x) -> Sem (Stop eo : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop ei : r1) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedRWithH :: forall extra param resource effect eo ei r r1. r1 ~ (extra ++ (Stop eo : r)) => r1 ~ ((extra ++ '[Stop eo]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop eo]) => (forall x. param -> (resource -> Sem r1 x) -> Sem (Stop eo : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop ei : r1) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedRWith_ :: forall extra param effect eo ei r r1. r1 ~ (extra ++ (Stop eo : r)) => r1 ~ ((extra ++ '[Stop eo]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop eo]) => (forall x. param -> Sem r1 x -> Sem (Stop eo : r) x) -> (forall r0 x. effect (Sem r0) x -> Sem (Stop ei : r1) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedR_ :: forall param resource effect eo ei r. (param -> Sem (Stop eo : r) resource) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop ei : r) x) -> InterpreterFor (Scoped param (effect !! ei) !! eo) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedResumableWith :: forall extra param resource effect err r r1. r1 ~ (extra ++ (Stop err : r)) => r1 ~ ((extra ++ '[Stop err]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop err]) => (forall x. param -> (resource -> Sem r1 x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem r1 x) -> InterpreterFor (Scoped param effect !! err) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedResumableWithH :: forall extra param resource effect err r r1. r1 ~ (extra ++ (Stop err : r)) => r1 ~ ((extra ++ '[Stop err]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop err]) => (forall x. param -> (resource -> Sem r1 x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r1 x) -> InterpreterFor (Scoped param effect !! err) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedResumableWith_ :: forall extra param effect err r r1. r1 ~ (extra ++ (Stop err : r)) => r1 ~ ((extra ++ '[Stop err]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop err]) => (forall x. param -> Sem r1 x -> Sem (Stop err : r) x) -> (forall r0 x. effect (Sem r0) x -> Sem r1 x) -> InterpreterFor (Scoped param effect !! err) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedResumable_ :: forall param resource effect err r. (param -> Sem (Stop err : r) resource) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped param effect !! err) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedWith :: forall extra param resource effect r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> (resource -> Sem r1 x) -> Sem r x) -> (forall m x. resource -> effect m x -> Sem r1 x) -> InterpreterFor (Scoped param effect) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedWithH :: forall extra resource param effect r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> (resource -> Sem r1 x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r1 x) -> InterpreterFor (Scoped param effect) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedWith_ :: forall extra param effect r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> Sem r1 x -> Sem r x) -> (forall m x. effect m x -> Sem r1 x) -> InterpreterFor (Scoped param effect) r
+ Polysemy.Conc.Interpreter.Semaphore: interpretSemaphoreQ :: Member (Embed IO) r => Int -> InterpreterFor Semaphore r
+ Polysemy.Conc.Interpreter.Semaphore: interpretSemaphoreQWith :: Member (Embed IO) r => QSem -> InterpreterFor Semaphore r
+ Polysemy.Conc.Interpreter.Semaphore: interpretSemaphoreT :: Member (Embed IO) r => Integer -> InterpreterFor Semaphore r
+ Polysemy.Conc.Interpreter.Semaphore: interpretSemaphoreTWith :: Member (Embed IO) r => TSem -> InterpreterFor Semaphore r
+ Polysemy.Conc.Queue: tryReadMaybe :: Member (Queue d) r => Sem r (Maybe d)
+ Polysemy.Conc.Race: timeoutStop :: TimeUnit u => Members [Race, Stop err] r => err -> u -> Sem r a -> Sem r a
+ Polysemy.Conc.Semaphore: data Semaphore :: Effect
+ Polysemy.Conc.Semaphore: interpretSemaphoreQ :: Member (Embed IO) r => Int -> InterpreterFor Semaphore r
+ Polysemy.Conc.Semaphore: interpretSemaphoreT :: Member (Embed IO) r => Integer -> InterpreterFor Semaphore r
+ Polysemy.Conc.Semaphore: signal :: forall r. Member Semaphore r => Sem r ()
+ Polysemy.Conc.Semaphore: wait :: forall r. Member Semaphore r => Sem r ()
- Polysemy.Conc: data Events (resource :: Type) (e :: Type) :: Effect
+ Polysemy.Conc: data Events (e :: Type) :: Effect
- Polysemy.Conc: data Scoped (resource :: Type) (effect :: Effect) :: Effect
+ Polysemy.Conc: data Scoped (param :: Type) (effect :: Effect) :: Effect
- Polysemy.Conc: interpretEventsChan :: forall e r. Members [Resource, Race, Async, Embed IO] r => InterpretersFor [Events (OutChan e) e, ChanConsumer e] r
+ Polysemy.Conc: interpretEventsChan :: forall e r. Members [Resource, Race, Async, Embed IO] r => InterpretersFor [Events e, EventConsumer e] r
- Polysemy.Conc: interpretMaskFinal :: Member (Final IO) r => InterpreterFor (Mask Restoration) r
+ Polysemy.Conc: interpretMaskFinal :: Member (Final IO) r => InterpreterFor Mask r
- Polysemy.Conc: interpretMonitorPure :: InterpreterFor (ScopedMonitor () action) r
+ Polysemy.Conc: interpretMonitorPure :: InterpreterFor (ScopedMonitor action) r
- Polysemy.Conc: interpretMonitorRestart :: forall t d r. Members [Time t d, Resource, Async, Race, Final IO] r => MonitorCheck r -> InterpreterFor (RestartingMonitor CancelResource) r
+ Polysemy.Conc: interpretMonitorRestart :: forall t d r. Members [Time t d, Resource, Async, Race, Final IO] r => MonitorCheck r -> InterpreterFor RestartingMonitor r
- Polysemy.Conc: interpretScoped :: forall resource effect r. (forall x. (resource -> Sem r x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem r x) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc: interpretScoped :: forall resource param effect r. (forall x. param -> (resource -> Sem r x) -> Sem r x) -> (forall m x. resource -> effect m x -> Sem r x) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc: interpretScopedAs :: forall resource effect r. Sem r resource -> (forall r0 x. resource -> effect (Sem r0) x -> Sem r x) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc: interpretScopedAs :: forall resource param effect r. (param -> Sem r resource) -> (forall m x. resource -> effect m x -> Sem r x) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc: interpretScopedH :: forall resource effect r. (forall x. (resource -> Sem r x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r x) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc: interpretScopedH :: forall resource param effect r. (forall x. param -> (resource -> Sem r x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r x) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc: interpretScopedResumable :: forall resource effect err r. (forall x. (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped resource effect !! err) r
+ Polysemy.Conc: interpretScopedResumable :: forall param resource effect err r. (forall x. param -> (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped param effect !! err) r
- Polysemy.Conc: interpretScopedResumableH :: forall resource effect err r. (forall x. (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) -> InterpreterFor (Scoped resource effect !! err) r
+ Polysemy.Conc: interpretScopedResumableH :: forall param resource effect err r. (forall x. param -> (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) -> InterpreterFor (Scoped param effect !! err) r
- Polysemy.Conc: interpretScopedResumableWith :: forall extra resource effect err r r1. r1 ~ ((extra ++ '[Stop err]) ++ r) => InsertAtIndex 1 '[Scoped resource effect !! err] r1 r ((Scoped resource effect !! err) : r1) (extra ++ '[Stop err]) => (forall x. (resource -> Sem r1 x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem r1 x) -> InterpreterFor (Scoped resource effect !! err) r
+ Polysemy.Conc: interpretScopedResumableWith :: forall extra param resource effect err r r1. r1 ~ (extra ++ (Stop err : r)) => r1 ~ ((extra ++ '[Stop err]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop err]) => (forall x. param -> (resource -> Sem r1 x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem r1 x) -> InterpreterFor (Scoped param effect !! err) r
- Polysemy.Conc: interpretScopedResumableWithH :: forall extra resource effect err r r1. r1 ~ ((extra ++ '[Stop err]) ++ r) => InsertAtIndex 1 '[Scoped resource effect !! err] r1 r ((Scoped resource effect !! err) : r1) (extra ++ '[Stop err]) => (forall x. (resource -> Sem r1 x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r1 x) -> InterpreterFor (Scoped resource effect !! err) r
+ Polysemy.Conc: interpretScopedResumableWithH :: forall extra param resource effect err r r1. r1 ~ (extra ++ (Stop err : r)) => r1 ~ ((extra ++ '[Stop err]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop err]) => (forall x. param -> (resource -> Sem r1 x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r1 x) -> InterpreterFor (Scoped param effect !! err) r
- Polysemy.Conc: interpretScopedResumableWith_ :: forall extra effect err r r1. r1 ~ ((extra ++ '[Stop err]) ++ r) => InsertAtIndex 1 '[Scoped () effect !! err] r1 r ((Scoped () effect !! err) : r1) (extra ++ '[Stop err]) => (forall x. Sem r1 x -> Sem (Stop err : r) x) -> (forall r0 x. effect (Sem r0) x -> Sem r1 x) -> InterpreterFor (Scoped () effect !! err) r
+ Polysemy.Conc: interpretScopedResumableWith_ :: forall extra param effect err r r1. r1 ~ (extra ++ (Stop err : r)) => r1 ~ ((extra ++ '[Stop err]) ++ r) => KnownList extra => KnownList (extra ++ '[Stop err]) => (forall x. param -> Sem r1 x -> Sem (Stop err : r) x) -> (forall r0 x. effect (Sem r0) x -> Sem r1 x) -> InterpreterFor (Scoped param effect !! err) r
- Polysemy.Conc: interpretScopedSync :: forall d r. Members [Resource, Race, Embed IO] r => InterpreterFor (Scoped (SyncResources (MVar d)) (Sync d)) r
+ Polysemy.Conc: interpretScopedSync :: forall d r. Members [Resource, Race, Embed IO] r => InterpreterFor (Scoped_ (Sync d)) r
- Polysemy.Conc: interpretScopedSyncAs :: forall d r. Members [Resource, Race, Embed IO] r => d -> InterpreterFor (Scoped (SyncResources (MVar d)) (Sync d)) r
+ Polysemy.Conc: interpretScopedSyncAs :: forall d r. Members [Resource, Race, Embed IO] r => d -> InterpreterFor (Scoped_ (Sync d)) r
- Polysemy.Conc: interpretScopedWith :: forall extra resource effect r r1. r1 ~ (extra ++ r) => InsertAtIndex 1 '[Scoped resource effect] r1 r (Scoped resource effect : r1) extra => (forall x. (resource -> Sem r1 x) -> Sem r x) -> (forall m x. resource -> effect m x -> Sem r1 x) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc: interpretScopedWith :: forall extra param resource effect r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> (resource -> Sem r1 x) -> Sem r x) -> (forall m x. resource -> effect m x -> Sem r1 x) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc: interpretScopedWithH :: forall extra resource effect r r1. r1 ~ (extra ++ r) => InsertAtIndex 1 '[Scoped resource effect] r1 r (Scoped resource effect : r1) extra => (forall x. (resource -> Sem r1 x) -> Sem r x) -> (forall m x. resource -> effect m x -> Tactical effect m r1 x) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc: interpretScopedWithH :: forall extra resource param effect r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> (resource -> Sem r1 x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r1 x) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc: interpretScopedWith_ :: forall extra effect r r1. r1 ~ (extra ++ r) => InsertAtIndex 1 '[Scoped () effect] r1 r (Scoped () effect : r1) extra => (forall x. Sem r1 x -> Sem r x) -> (forall m x. effect m x -> Sem r1 x) -> InterpreterFor (Scoped () effect) r
+ Polysemy.Conc: interpretScopedWith_ :: forall extra param effect r r1. r1 ~ (extra ++ r) => KnownList extra => (forall x. param -> Sem r1 x -> Sem r x) -> (forall m x. effect m x -> Sem r1 x) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc: interpretUninterruptibleMaskFinal :: Member (Final IO) r => InterpreterFor (UninterruptibleMask Restoration) r
+ Polysemy.Conc: interpretUninterruptibleMaskFinal :: Member (Final IO) r => InterpreterFor UninterruptibleMask r
- Polysemy.Conc: lock :: forall l r a. Members [Sync l, Resource] r => l -> Sem r a -> Sem r a
+ Polysemy.Conc: lock :: forall r a. Member Lock r => Sem r a -> Sem r a
- Polysemy.Conc: mask :: forall resource r. Member (Mask resource) r => InterpreterFor RestoreMask r
+ Polysemy.Conc: mask :: Member Mask r => InterpreterFor RestoreMask r
- Polysemy.Conc: publish :: forall e resource r. Member (Events resource e) r => e -> Sem r ()
+ Polysemy.Conc: publish :: forall e r. Member (Events e) r => e -> Sem r ()
- Polysemy.Conc: restart :: forall resource r. Member (ScopedMonitor resource Restart) r => InterpreterFor (Monitor Restart) r
+ Polysemy.Conc: restart :: Member (ScopedMonitor Restart) r => InterpreterFor (Monitor Restart) r
- Polysemy.Conc: runScoped :: forall resource effect r. (forall x. (resource -> Sem r x) -> Sem r x) -> (resource -> InterpreterFor effect r) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc: runScoped :: forall resource param effect r. (forall x. param -> (resource -> Sem r x) -> Sem r x) -> (resource -> InterpreterFor effect r) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc: runScopedAs :: forall resource effect r. Sem r resource -> (resource -> InterpreterFor effect r) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc: runScopedAs :: forall resource param effect r. (param -> Sem r resource) -> (resource -> InterpreterFor effect r) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc: scheduleAsync :: forall res b r a. Members [ScopedSync res (), Async, Race] r => Sem r b -> (Async (Maybe b) -> Sem (Sync () : r) () -> Sem (Sync () : r) a) -> Sem r a
+ Polysemy.Conc: scheduleAsync :: forall b r a. Members [ScopedSync (), Async, Race] r => Sem r b -> (Async (Maybe b) -> Sem (Sync () : r) () -> Sem (Sync () : r) a) -> Sem r a
- Polysemy.Conc: scoped :: forall resource effect r. Member (Scoped resource effect) r => InterpreterFor effect r
+ Polysemy.Conc: scoped :: forall param effect r. Member (Scoped param effect) r => param -> InterpreterFor effect r
- Polysemy.Conc: subscribe :: forall e resource r. Member (Scoped (EventResource resource) (Consume e)) r => InterpreterFor (Consume e) r
+ Polysemy.Conc: subscribe :: forall e r. Member (Scoped_ (Consume e)) r => InterpreterFor (Consume e) r
- Polysemy.Conc: subscribeLoop :: forall e token r. Member (EventConsumer token e) r => (e -> Sem r ()) -> Sem r ()
+ Polysemy.Conc: subscribeLoop :: forall e r. Member (EventConsumer e) r => (e -> Sem r ()) -> Sem r ()
- Polysemy.Conc: subscribeWhile :: forall e token r. Member (EventConsumer token e) r => (e -> Sem r Bool) -> Sem r ()
+ Polysemy.Conc: subscribeWhile :: forall e r. Member (EventConsumer e) r => (e -> Sem r Bool) -> Sem r ()
- Polysemy.Conc: type ConcStack = [UninterruptibleMask Restoration, Mask Restoration, Race, Async, Resource, Embed IO, Final IO]
+ Polysemy.Conc: type ConcStack = [UninterruptibleMask, Mask, Gates, Race, Async, Resource, Embed IO, Final IO]
- Polysemy.Conc: type EventConsumer token e = Scoped (EventResource token) (Consume e)
+ Polysemy.Conc: type EventConsumer e = Scoped_ (Consume e)
- Polysemy.Conc: type Mask resource = Scoped (MaskResource resource) RestoreMask
+ Polysemy.Conc: type Mask = Scoped_ RestoreMask
- Polysemy.Conc: type RestartingMonitor (resource :: Type) = ScopedMonitor resource Restart
+ Polysemy.Conc: type RestartingMonitor = ScopedMonitor Restart
- Polysemy.Conc: type ScopedMonitor (resource :: Type) (action :: Type) = Scoped (MonitorResource resource) (Monitor action)
+ Polysemy.Conc: type ScopedMonitor (action :: Type) = Scoped_ (Monitor action)
- Polysemy.Conc: type ScopedSync res a = Scoped (SyncResources res) (Sync a)
+ Polysemy.Conc: type ScopedSync a = Scoped_ (Sync a)
- Polysemy.Conc: type UninterruptibleMask resource = Scoped (UninterruptibleMaskResource resource) RestoreMask
+ Polysemy.Conc: type UninterruptibleMask = Scoped_ RestoreMask
- Polysemy.Conc: uninterruptibleMask :: forall resource r. Member (UninterruptibleMask resource) r => InterpreterFor RestoreMask r
+ Polysemy.Conc: uninterruptibleMask :: Member UninterruptibleMask r => InterpreterFor RestoreMask r
- Polysemy.Conc: withMonitor :: forall resource action r. Member (ScopedMonitor resource action) r => InterpreterFor (Monitor action) r
+ Polysemy.Conc: withMonitor :: forall action r. Member (ScopedMonitor action) r => InterpreterFor (Monitor action) r
- Polysemy.Conc: withSync :: forall d res r. Member (ScopedSync res d) r => InterpreterFor (Sync d) r
+ Polysemy.Conc: withSync :: forall d r. Member (ScopedSync d) r => InterpreterFor (Sync d) r
- Polysemy.Conc.Async: scheduleAsync :: forall res b r a. Members [ScopedSync res (), Async, Race] r => Sem r b -> (Async (Maybe b) -> Sem (Sync () : r) () -> Sem (Sync () : r) a) -> Sem r a
+ Polysemy.Conc.Async: scheduleAsync :: forall b r a. Members [ScopedSync (), Async, Race] r => Sem r b -> (Async (Maybe b) -> Sem (Sync () : r) () -> Sem (Sync () : r) a) -> Sem r a
- Polysemy.Conc.Effect.Events: [Publish] :: e -> Events resource e m ()
+ Polysemy.Conc.Effect.Events: [Publish] :: e -> Events e m ()
- Polysemy.Conc.Effect.Events: data Events (resource :: Type) (e :: Type) :: Effect
+ Polysemy.Conc.Effect.Events: data Events (e :: Type) :: Effect
- Polysemy.Conc.Effect.Events: publish :: forall e resource r. Member (Events resource e) r => e -> Sem r ()
+ Polysemy.Conc.Effect.Events: publish :: forall e r. Member (Events e) r => e -> Sem r ()
- Polysemy.Conc.Effect.Events: subscribe :: forall e resource r. Member (Scoped (EventResource resource) (Consume e)) r => InterpreterFor (Consume e) r
+ Polysemy.Conc.Effect.Events: subscribe :: forall e r. Member (Scoped_ (Consume e)) r => InterpreterFor (Consume e) r
- Polysemy.Conc.Effect.Mask: mask :: forall resource r. Member (Mask resource) r => InterpreterFor RestoreMask r
+ Polysemy.Conc.Effect.Mask: mask :: Member Mask r => InterpreterFor RestoreMask r
- Polysemy.Conc.Effect.Mask: type Mask resource = Scoped (MaskResource resource) RestoreMask
+ Polysemy.Conc.Effect.Mask: type Mask = Scoped_ RestoreMask
- Polysemy.Conc.Effect.Mask: type UninterruptibleMask resource = Scoped (UninterruptibleMaskResource resource) RestoreMask
+ Polysemy.Conc.Effect.Mask: type UninterruptibleMask = Scoped_ RestoreMask
- Polysemy.Conc.Effect.Mask: uninterruptibleMask :: forall resource r. Member (UninterruptibleMask resource) r => InterpreterFor RestoreMask r
+ Polysemy.Conc.Effect.Mask: uninterruptibleMask :: Member UninterruptibleMask r => InterpreterFor RestoreMask r
- Polysemy.Conc.Effect.Monitor: restart :: forall resource r. Member (ScopedMonitor resource Restart) r => InterpreterFor (Monitor Restart) r
+ Polysemy.Conc.Effect.Monitor: restart :: Member (ScopedMonitor Restart) r => InterpreterFor (Monitor Restart) r
- Polysemy.Conc.Effect.Monitor: type RestartingMonitor (resource :: Type) = ScopedMonitor resource Restart
+ Polysemy.Conc.Effect.Monitor: type RestartingMonitor = ScopedMonitor Restart
- Polysemy.Conc.Effect.Monitor: type ScopedMonitor (resource :: Type) (action :: Type) = Scoped (MonitorResource resource) (Monitor action)
+ Polysemy.Conc.Effect.Monitor: type ScopedMonitor (action :: Type) = Scoped_ (Monitor action)
- Polysemy.Conc.Effect.Monitor: withMonitor :: forall resource action r. Member (ScopedMonitor resource action) r => InterpreterFor (Monitor action) r
+ Polysemy.Conc.Effect.Monitor: withMonitor :: forall action r. Member (ScopedMonitor action) r => InterpreterFor (Monitor action) r
- Polysemy.Conc.Effect.Scoped: [InScope] :: forall resource effect m a. (resource -> m a) -> Scoped resource effect m a
+ Polysemy.Conc.Effect.Scoped: [InScope] :: forall param effect m a. param -> m a -> Scoped param effect m a
- Polysemy.Conc.Effect.Scoped: [Run] :: forall resource effect m a. resource -> effect m a -> Scoped resource effect m a
+ Polysemy.Conc.Effect.Scoped: [Run] :: forall param effect m a. effect m a -> Scoped param effect m a
- Polysemy.Conc.Effect.Scoped: data Scoped (resource :: Type) (effect :: Effect) :: Effect
+ Polysemy.Conc.Effect.Scoped: data Scoped (param :: Type) (effect :: Effect) :: Effect
- Polysemy.Conc.Effect.Scoped: scoped :: forall resource effect r. Member (Scoped resource effect) r => InterpreterFor effect r
+ Polysemy.Conc.Effect.Scoped: scoped :: forall param effect r. Member (Scoped param effect) r => param -> InterpreterFor effect r
- Polysemy.Conc.Effect.Sync: type ScopedSync res a = Scoped (SyncResources res) (Sync a)
+ Polysemy.Conc.Effect.Sync: type ScopedSync a = Scoped_ (Sync a)
- Polysemy.Conc.Events: subscribeLoop :: forall e token r. Member (EventConsumer token e) r => (e -> Sem r ()) -> Sem r ()
+ Polysemy.Conc.Events: subscribeLoop :: forall e r. Member (EventConsumer e) r => (e -> Sem r ()) -> Sem r ()
- Polysemy.Conc.Events: subscribeWhile :: forall e token r. Member (EventConsumer token e) r => (e -> Sem r Bool) -> Sem r ()
+ Polysemy.Conc.Events: subscribeWhile :: forall e r. Member (EventConsumer e) r => (e -> Sem r Bool) -> Sem r ()
- Polysemy.Conc.Interpreter.Events: interpretConsumeChan :: forall e r. Member (Embed IO) r => EventChan e -> InterpreterFor (Consume e) r
+ Polysemy.Conc.Interpreter.Events: interpretConsumeChan :: forall e r. Member (Embed IO) r => OutChan e -> InterpreterFor (Consume e) r
- Polysemy.Conc.Interpreter.Events: interpretEventsChan :: forall e r. Members [Resource, Race, Async, Embed IO] r => InterpretersFor [Events (OutChan e) e, ChanConsumer e] r
+ Polysemy.Conc.Interpreter.Events: interpretEventsChan :: forall e r. Members [Resource, Race, Async, Embed IO] r => InterpretersFor [Events e, EventConsumer e] r
- Polysemy.Conc.Interpreter.Events: interpretEventsInChan :: forall e r. Member (Embed IO) r => InChan e -> InterpreterFor (Events (OutChan e) e) r
+ Polysemy.Conc.Interpreter.Events: interpretEventsInChan :: forall e r. Member (Embed IO) r => InChan e -> InterpreterFor (Events e) r
- Polysemy.Conc.Interpreter.Events: type EventConsumer token e = Scoped (EventResource token) (Consume e)
+ Polysemy.Conc.Interpreter.Events: type EventConsumer e = Scoped_ (Consume e)
- Polysemy.Conc.Interpreter.Mask: interpretMaskFinal :: Member (Final IO) r => InterpreterFor (Mask Restoration) r
+ Polysemy.Conc.Interpreter.Mask: interpretMaskFinal :: Member (Final IO) r => InterpreterFor Mask r
- Polysemy.Conc.Interpreter.Mask: interpretUninterruptibleMaskFinal :: Member (Final IO) r => InterpreterFor (UninterruptibleMask Restoration) r
+ Polysemy.Conc.Interpreter.Mask: interpretUninterruptibleMaskFinal :: Member (Final IO) r => InterpreterFor UninterruptibleMask r
- Polysemy.Conc.Interpreter.Monitor: interpretMonitorPure :: InterpreterFor (ScopedMonitor () action) r
+ Polysemy.Conc.Interpreter.Monitor: interpretMonitorPure :: InterpreterFor (ScopedMonitor action) r
- Polysemy.Conc.Interpreter.Monitor: interpretMonitorRestart :: forall t d r. Members [Time t d, Resource, Async, Race, Final IO] r => MonitorCheck r -> InterpreterFor (RestartingMonitor CancelResource) r
+ Polysemy.Conc.Interpreter.Monitor: interpretMonitorRestart :: forall t d r. Members [Time t d, Resource, Async, Race, Final IO] r => MonitorCheck r -> InterpreterFor RestartingMonitor r
- Polysemy.Conc.Interpreter.Scoped: interpretScoped :: forall resource effect r. (forall x. (resource -> Sem r x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem r x) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScoped :: forall resource param effect r. (forall x. param -> (resource -> Sem r x) -> Sem r x) -> (forall m x. resource -> effect m x -> Sem r x) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc.Interpreter.Scoped: interpretScopedAs :: forall resource effect r. Sem r resource -> (forall r0 x. resource -> effect (Sem r0) x -> Sem r x) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedAs :: forall resource param effect r. (param -> Sem r resource) -> (forall m x. resource -> effect m x -> Sem r x) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc.Interpreter.Scoped: interpretScopedH :: forall resource effect r. (forall x. (resource -> Sem r x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r x) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedH :: forall resource param effect r. (forall x. param -> (resource -> Sem r x) -> Sem r x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r x) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc.Interpreter.Scoped: interpretScopedResumable :: forall resource effect err r. (forall x. (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped resource effect !! err) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedResumable :: forall param resource effect err r. (forall x. param -> (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Sem (Stop err : r) x) -> InterpreterFor (Scoped param effect !! err) r
- Polysemy.Conc.Interpreter.Scoped: interpretScopedResumableH :: forall resource effect err r. (forall x. (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) -> InterpreterFor (Scoped resource effect !! err) r
+ Polysemy.Conc.Interpreter.Scoped: interpretScopedResumableH :: forall param resource effect err r. (forall x. param -> (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) -> (forall r0 x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) -> InterpreterFor (Scoped param effect !! err) r
- Polysemy.Conc.Interpreter.Scoped: runScoped :: forall resource effect r. (forall x. (resource -> Sem r x) -> Sem r x) -> (resource -> InterpreterFor effect r) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc.Interpreter.Scoped: runScoped :: forall resource param effect r. (forall x. param -> (resource -> Sem r x) -> Sem r x) -> (resource -> InterpreterFor effect r) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc.Interpreter.Scoped: runScopedAs :: forall resource effect r. Sem r resource -> (resource -> InterpreterFor effect r) -> InterpreterFor (Scoped resource effect) r
+ Polysemy.Conc.Interpreter.Scoped: runScopedAs :: forall resource param effect r. (param -> Sem r resource) -> (resource -> InterpreterFor effect r) -> InterpreterFor (Scoped param effect) r
- Polysemy.Conc.Interpreter.Stack: type ConcStack = [UninterruptibleMask Restoration, Mask Restoration, Race, Async, Resource, Embed IO, Final IO]
+ Polysemy.Conc.Interpreter.Stack: type ConcStack = [UninterruptibleMask, Mask, Gates, Race, Async, Resource, Embed IO, Final IO]
- Polysemy.Conc.Interpreter.Sync: interpretScopedSync :: forall d r. Members [Resource, Race, Embed IO] r => InterpreterFor (Scoped (SyncResources (MVar d)) (Sync d)) r
+ Polysemy.Conc.Interpreter.Sync: interpretScopedSync :: forall d r. Members [Resource, Race, Embed IO] r => InterpreterFor (Scoped_ (Sync d)) r
- Polysemy.Conc.Interpreter.Sync: interpretScopedSyncAs :: forall d r. Members [Resource, Race, Embed IO] r => d -> InterpreterFor (Scoped (SyncResources (MVar d)) (Sync d)) r
+ Polysemy.Conc.Interpreter.Sync: interpretScopedSyncAs :: forall d r. Members [Resource, Race, Embed IO] r => d -> InterpreterFor (Scoped_ (Sync d)) r
- Polysemy.Conc.Sync: modify :: forall a b res r. Members [Sync a, Mask res, Resource] r => (a -> Sem r (a, b)) -> Sem r b
+ Polysemy.Conc.Sync: modify :: forall a b r. Members [Sync a, Mask, Resource] r => (a -> Sem r (a, b)) -> Sem r b
- Polysemy.Conc.Sync: modifyMasked :: forall a b res r. Members [Sync a, Mask res, Resource] r => (a -> Sem r (a, b)) -> Sem r b
+ Polysemy.Conc.Sync: modifyMasked :: forall a b r. Members [Sync a, Mask, Resource] r => (a -> Sem r (a, b)) -> Sem r b
- Polysemy.Conc.Sync: modifyMasked_ :: forall a res r. Members [Sync a, Mask res, Resource] r => (a -> Sem r a) -> Sem r ()
+ Polysemy.Conc.Sync: modifyMasked_ :: forall a r. Members [Sync a, Mask, Resource] r => (a -> Sem r a) -> Sem r ()
- Polysemy.Conc.Sync: modify_ :: forall a res r. Members [Sync a, Mask res, Resource] r => (a -> Sem r a) -> Sem r ()
+ Polysemy.Conc.Sync: modify_ :: forall a r. Members [Sync a, Mask, Resource] r => (a -> Sem r a) -> Sem r ()
- Polysemy.Conc.Sync: use :: forall a b res r. Members [Sync a, Mask res, Resource] r => (a -> Sem r b) -> Sem r b
+ Polysemy.Conc.Sync: use :: forall a b r. Members [Sync a, Mask, Resource] r => (a -> Sem r b) -> Sem r b
- Polysemy.Conc.Sync: useMasked :: forall a b res r. Members [Sync a, Mask res, Resource] r => (a -> Sem r b) -> Sem r b
+ Polysemy.Conc.Sync: useMasked :: forall a b r. Members [Sync a, Mask, Resource] r => (a -> Sem r b) -> Sem r b
- Polysemy.Conc.Sync: withSync :: forall d res r. Member (ScopedSync res d) r => InterpreterFor (Sync d) r
+ Polysemy.Conc.Sync: withSync :: forall d r. Member (ScopedSync d) r => InterpreterFor (Sync d) r

Files

+ changelog.md view
@@ -0,0 +1,68 @@+# 0.10.0.0++## Breaking++* Add a parameter to `Scoped` that allows arbitrary data to be passed to the scoped interpreter via `scoped`.+* Remove the `resource` parameter from `Scoped`.++## Other++* Add `Queue.tryReadMaybe`, a variant of `readMaybe` that does not wait.+* Add variants of the combined `Scoped` interpreters in which the `Resumable` is inside the scope.+* Add `Semaphore`, abstracting `QSem` or `TSem`.+* Add `timeoutStop`, a variant of `timeout` that calls `Polysemy.Resume.stop`.+* Add `Lock`, a mutex effect.+* Add `withAsyncGated`, a variant of `withAsync` that requires the async action to signal the sync action to start.+* Add `Gate`, a synchronization point effect.+* Add variants of `subscribeWhile` and `subscribeLoop` that use `Gate` for synchronization and run in a new thread.+* Add pure interpreters for `Mask`.+* Add more variants of `subscribeLoop` that return matching elements.+* Add `Gates` to `ConcStack`.+* Add `rescope`, a reinterpreter for `Scoped` that may extend the scope parameters.++# 0.9.0.0++* Add the missing `MVar` combinators for `Sync` that bracket an action with `mask`.+* Export `Restoration`.+* Add `interpretProcessOutputLeft/Right`.++# 0.6.1.0++* Add `SyncRead`, a read-only variant of `Sync`.+* Change `withAsync` to use `finally` instead of `bracket`, since the latter causes `AsyncCancelled` to be masked,+  preventing the action from being cancelled unless it runs an interruptible action.++# 0.6.0.0++* Add `Resumable` support for `Scoped`.+* Add `Scoped` interpreters that allow the allocator to interpret additional effects used by the handler.++# 0.5.0.0++* Add `mask` effects.+* Add `Monitor`, an effect that repeatedly checks a condition and restarts a region when it is met.+* Add interpreter combinators for `Scoped`.+* Add a runner for the default `Conc` stack.++# 0.4.0.0++* Add `lock`, a combinator for protecting a region with a mutex.+* Add `scheduleAsync`, a combinator for running an action async that allows the handle to be used before the thread+  starts+* Change the default signal handler for `Interrupt` to `CatchInfo`, catching repeated signals.++# 0.3.0.0++* Change `Race.timeout` to take a `Sem` for the fallback instead of a pure value.+* Export all `Queue` constructors from `Polysemy.Conc.Queue`.+* Export all `Sync` constructors from `Polysemy.Conc.Sync`.+* Move all interpreters to `Polysemy.Conc.Interpreter`.++# 0.2.0.0+* Add `read*` constructors for `Sync`+* Add `subscribeWhile`, a combinator that consumes events until a condition is met+* Add looping combinators for `Queue`+* Add `retry`, a combinator that runs an action repeatedly until it returns `Right` or a timeout is hit+* Add `Scoped`, an effect for local resource scoping+* Add `withAsync`, a bracketing combinator that runs an async action while the main action runs+* Add `interpretAtomic`, a convenience interpreter for `AtomicState` that runs `runAtomicStateTVar`
lib/Polysemy/Conc.hs view
@@ -31,11 +31,36 @@   interpretSync,   interpretSyncAs,   withSync,-  lock,   interpretScopedSync,   interpretScopedSyncAs,   syncRead, +  -- * Lock+  Lock,+  lock,+  lockOr,+  lockOrSkip,+  lockOrSkip_,++  -- ** Interpreters+  interpretLockReentrant,+  interpretLockPermissive,++  -- * Semaphores+  Semaphore,++  -- ** Interpreters+  interpretSemaphoreQ,+  interpretSemaphoreT,++  -- * Gate+  Gate,+  Gates,++  -- ** Interpreters+  interpretGates,+  interpretGate,+   -- * Racing   -- $race   Race,@@ -47,6 +72,7 @@   timeoutAs_,   timeoutU,   timeoutMaybe,+  timeoutStop,   retrying,   retryingWithError, @@ -68,13 +94,23 @@   publish,   consume,   subscribe,+  subscribeGated,+  subscribeAsync,   subscribeWhile,+  subscribeWhileGated,+  subscribeWhileAsync,   subscribeLoop,-  EventResource,-  EventChan,-  ChanEvents,+  subscribeLoopGated,+  subscribeLoopAsync,+  subscribeFind,+  subscribeFirstJust,+  subscribeElem,+  consumeWhile,+  consumeLoop,+  consumeFind,+  consumeFirstJust,+  consumeElem,   EventConsumer,-  ChanConsumer,    -- ** Interpreters   interpretEventsChan,@@ -97,25 +133,44 @@   -- * Interpreters   interpretMaskFinal,   interpretUninterruptibleMaskFinal,+  interpretMaskPure,+  interpretUninterruptibleMaskPure,    -- * Scoped Effects   Scoped,+  Scoped_,   scoped,+  scoped_,+  rescope,    -- ** Interpreters-  runScoped,-  runScopedAs,   interpretScoped,   interpretScopedH,+  interpretScopedH',   interpretScopedAs,-  interpretScopedResumable,-  interpretScopedResumableH,   interpretScopedWith,   interpretScopedWithH,   interpretScopedWith_,+  runScoped,+  runScopedAs,+  interpretScopedResumable,+  interpretScopedResumableH,+  interpretScopedResumable_,   interpretScopedResumableWith,   interpretScopedResumableWithH,   interpretScopedResumableWith_,+  interpretResumableScoped,+  interpretResumableScopedH,+  interpretResumableScoped_,+  interpretResumableScopedWith,+  interpretResumableScopedWithH,+  interpretResumableScopedWith_,+  interpretScopedR,+  interpretScopedRH,+  interpretScopedR_,+  interpretScopedRWith,+  interpretScopedRWithH,+  interpretScopedRWith_,    -- * Monitoring   Monitor,@@ -124,7 +179,6 @@   restart,   Restart,   RestartingMonitor,-  MonitorResource (MonitorResource),   ScopedMonitor,    -- ** Interpreters@@ -143,6 +197,8 @@   withAsync_,   scheduleAsync,   scheduleAsyncIO,+  withAsyncGated,+  withAsyncGated_, ) where  import Polysemy.Conc.Async (@@ -150,17 +206,27 @@   scheduleAsyncIO,   withAsync,   withAsyncBlock,+  withAsyncGated,+  withAsyncGated_,   withAsync_,   ) import Polysemy.Conc.AtomicState (interpretAtomic) import Polysemy.Conc.Data.QueueResult (QueueResult) import Polysemy.Conc.Effect.Critical (Critical)-import Polysemy.Conc.Effect.Events (Consume, EventResource, Events, consume, publish, subscribe)+import Polysemy.Conc.Effect.Events (Consume, Events, consume, publish, subscribe)+import Polysemy.Conc.Effect.Gate (Gate, Gates) import Polysemy.Conc.Effect.Interrupt (Interrupt)-import Polysemy.Conc.Effect.Mask (Mask, UninterruptibleMask, mask, restore, uninterruptibleMask)+import Polysemy.Conc.Effect.Lock (Lock, lock, lockOr, lockOrSkip, lockOrSkip_)+import Polysemy.Conc.Effect.Mask (+  Mask,+  Restoration,+  UninterruptibleMask,+  mask,+  restore,+  uninterruptibleMask,+  ) import Polysemy.Conc.Effect.Monitor (   Monitor,-  MonitorResource (MonitorResource),   Restart,   RestartingMonitor,   ScopedMonitor,@@ -170,14 +236,34 @@   ) import Polysemy.Conc.Effect.Queue (Queue) import Polysemy.Conc.Effect.Race (Race, race, timeout)-import Polysemy.Conc.Effect.Scoped (Scoped, scoped)+import Polysemy.Conc.Effect.Scoped (Scoped, Scoped_, scoped, scoped_, rescope)+import Polysemy.Conc.Effect.Semaphore (Semaphore) import Polysemy.Conc.Effect.Sync (ScopedSync, Sync) import Polysemy.Conc.Effect.SyncRead (SyncRead)-import Polysemy.Conc.Events (subscribeLoop, subscribeWhile)+import Polysemy.Conc.Events (+  consumeElem,+  consumeFind,+  consumeFirstJust,+  consumeLoop,+  consumeWhile,+  subscribeAsync,+  subscribeElem,+  subscribeFind,+  subscribeFirstJust,+  subscribeGated,+  subscribeLoop,+  subscribeLoopAsync,+  subscribeLoopGated,+  subscribeWhile,+  subscribeWhileAsync,+  subscribeWhileGated,+  ) import Polysemy.Conc.Interpreter.Critical (interpretCritical, interpretCriticalNull)-import Polysemy.Conc.Interpreter.Events (ChanConsumer, ChanEvents, EventChan, EventConsumer, interpretEventsChan)+import Polysemy.Conc.Interpreter.Events (EventConsumer, interpretEventsChan)+import Polysemy.Conc.Interpreter.Gate (interpretGate, interpretGates) import Polysemy.Conc.Interpreter.Interrupt (interpretInterrupt, interpretInterruptNull, interpretInterruptOnce)-import Polysemy.Conc.Interpreter.Mask (Restoration, interpretMaskFinal, interpretUninterruptibleMaskFinal)+import Polysemy.Conc.Interpreter.Lock (interpretLockPermissive, interpretLockReentrant)+import Polysemy.Conc.Interpreter.Mask (interpretMaskFinal, interpretMaskPure, interpretUninterruptibleMaskFinal, interpretUninterruptibleMaskPure) import Polysemy.Conc.Interpreter.Monitor (interpretMonitorPure, interpretMonitorRestart) import Polysemy.Conc.Interpreter.Queue.Pure (   interpretQueueListReadOnlyAtomic,@@ -189,29 +275,43 @@ import Polysemy.Conc.Interpreter.Queue.TBM (interpretQueueTBM) import Polysemy.Conc.Interpreter.Race (interpretRace) import Polysemy.Conc.Interpreter.Scoped (+  interpretResumableScoped,+  interpretResumableScopedH,+  interpretResumableScopedWith,+  interpretResumableScopedWithH,+  interpretResumableScopedWith_,+  interpretResumableScoped_,   interpretScoped,   interpretScopedAs,   interpretScopedH,+  interpretScopedR,+  interpretScopedRH,+  interpretScopedRWith,+  interpretScopedRWithH,+  interpretScopedRWith_,+  interpretScopedR_,   interpretScopedResumable,   interpretScopedResumableH,   interpretScopedResumableWith,   interpretScopedResumableWithH,   interpretScopedResumableWith_,+  interpretScopedResumable_,   interpretScopedWith,   interpretScopedWithH,   interpretScopedWith_,   runScoped,-  runScopedAs,+  runScopedAs, interpretScopedH',   )+import Polysemy.Conc.Interpreter.Semaphore (interpretSemaphoreQ, interpretSemaphoreT) import Polysemy.Conc.Interpreter.Stack (ConcStack, runConc) import Polysemy.Conc.Interpreter.Sync (interpretScopedSync, interpretScopedSyncAs, interpretSync, interpretSyncAs) import Polysemy.Conc.Interpreter.SyncRead (syncRead) import Polysemy.Conc.Monitor (ClockSkewConfig (ClockSkewConfig), clockSkewConfig, monitorClockSkew) import Polysemy.Conc.Queue (loop, loopOr) import Polysemy.Conc.Queue.Result (resultToMaybe)-import Polysemy.Conc.Race (race_, timeoutAs, timeoutAs_, timeoutMaybe, timeoutU, timeout_)+import Polysemy.Conc.Race (race_, timeoutAs, timeoutAs_, timeoutMaybe, timeoutStop, timeoutU, timeout_) import Polysemy.Conc.Retry (retrying, retryingWithError)-import Polysemy.Conc.Sync (lock, withSync)+import Polysemy.Conc.Sync (withSync)  -- $intro -- This library provides an assortment of tools for concurrency-related tasks:@@ -255,7 +355,7 @@ -- Usage is straightforward: -- -- @--- prog :: Member (Mask resource) r+-- prog :: Member Mask r -- prog = --  mask do --    doMaskedThing
lib/Polysemy/Conc/Async.hs view
@@ -4,7 +4,9 @@ import qualified Control.Concurrent.Async as Base import Polysemy.Time (MilliSeconds (MilliSeconds), TimeUnit) +import Polysemy.Conc.Effect.Gate (Gate, gate, withGate) import Polysemy.Conc.Effect.Race (Race)+import Polysemy.Conc.Effect.Scoped (Scoped_) import qualified Polysemy.Conc.Effect.Sync as Sync import Polysemy.Conc.Effect.Sync (ScopedSync, Sync) import Polysemy.Conc.Interpreter.Sync (interpretSync)@@ -25,7 +27,7 @@   finally (use handle) (cancel handle)  -- |Run the first action asynchronously while the second action executes, then cancel the first action.--- Passes the handle into the action to allow it to await its result.+-- Passes the handle into the sync action to allow it to await the async action's result. -- -- When cancelling, this variant will wait for the specified interval for the thread to be gone. withAsyncWait ::@@ -40,7 +42,7 @@   finally (use handle) (Race.timeoutU interval (cancel handle))  -- |Run the first action asynchronously while the second action executes, then cancel the first action.--- Passes the handle into the action to allow it to await its result.+-- Passes the handle into the sync action to allow it to await the async action's result. -- -- When cancelling, this variant will wait for 500ms for the thread to be gone. withAsync ::@@ -80,13 +82,13 @@ --   start -- now makeRequest is executed -- @ scheduleAsync ::-  ∀ res b r a .-  Members [ScopedSync res (), Async, Race] r =>+  ∀ b r a .+  Members [ScopedSync (), Async, Race] r =>   Sem r b ->   (Base.Async (Maybe b) -> Sem (Sync () : r) () -> Sem (Sync () : r) a) ->   Sem r a scheduleAsync mb f =-  withSync @() @res do+  withSync @() do     h <- async do       Sync.block @()       raise mb@@ -105,3 +107,37 @@       Sync.block @()       raise mb     f h (Sync.putBlock ())++-- |Run the first action asynchronously while the second action executes, then cancel the first action.+--+-- The second action will only start when the first action calls 'Polysemy.Conc.Gate.signal'.+--+-- Passes the handle into the sync action to allow it to await the async action's result.+--+-- This can be used to ensure that the async action has acquired its resources before the main action starts.+withAsyncGated ::+  ∀ b r a .+  Members [Scoped_ Gate, Resource, Race, Async] r =>+  Sem (Gate : r) b ->+  (Base.Async (Maybe b) -> Sem r a) ->+  Sem r a+withAsyncGated mb use =+  withGate $ withAsync mb \ h -> do+    gate+    raise (use h)++-- |Run the first action asynchronously while the second action executes, then cancel the first action.+--+-- The second action will only start when the first action calls 'Polysemy.Conc.Gate.signal'.+--+-- This can be used to ensure that the async action has acquired its resources before the main action starts.+withAsyncGated_ ::+  ∀ b r a .+  Members [Scoped_ Gate, Resource, Race, Async] r =>+  Sem (Gate : r) b ->+  Sem r a ->+  Sem r a+withAsyncGated_ mb use =+  withGate $ withAsync_ mb do+    gate+    raise use
lib/Polysemy/Conc/Effect/Events.hs view
@@ -3,23 +3,18 @@ -- |Description: Events/Consume Effects, Internal module Polysemy.Conc.Effect.Events where -import Polysemy.Conc.Effect.Scoped (Scoped, scoped)---- |Marker for the 'Scoped' resource for 'Events'.-newtype EventResource resource =-  EventResource { unEventToken :: resource }-  deriving stock (Eq, Show, Generic)+import Polysemy.Conc.Effect.Scoped (Scoped_, scoped_)  -- |An event publisher that can be consumed from multiple threads.-data Events (resource :: Type) (e :: Type) :: Effect where-  Publish :: e -> Events resource e m ()+data Events (e :: Type) :: Effect where+  Publish :: e -> Events e m ()  makeSem_ ''Events  -- |Publish one event. publish ::-  ∀ e resource r .-  Member (Events resource e) r =>+  ∀ e r .+  Member (Events e) r =>   e ->   Sem r () @@ -38,8 +33,8 @@ -- |Create a new scope for 'Events', causing the nested program to get its own copy of the event stream. -- To be used with 'Polysemy.Conc.interpretEventsChan'. subscribe ::-  ∀ e resource r .-  Member (Scoped (EventResource resource) (Consume e)) r =>+  ∀ e r .+  Member (Scoped_ (Consume e)) r =>   InterpreterFor (Consume e) r subscribe =-  scoped @(EventResource resource)+  scoped_
+ lib/Polysemy/Conc/Effect/Gate.hs view
@@ -0,0 +1,28 @@+{-# options_haddock prune #-}++-- |Description: Gate effect, Internal+module Polysemy.Conc.Effect.Gate where++import Polysemy.Conc.Effect.Scoped (Scoped_, scoped_)++-- |A single-use synchronization point that blocks all consumers who called 'gate' until 'signal' is called.+--+-- The constructors are exported from [Polysemy.Conc.Gate]("Polysemy.Conc.Gate").+data Gate :: Effect where+  Signal :: Gate m ()+  Gate :: Gate m ()++makeSem ''Gate++-- |Convenience alias for scoped 'Gate'.+type Gates =+  Scoped_ Gate++-- |Run an action with a locally scoped 'Gate' effect.+--+-- This avoids a dependency on @'Embed' 'IO'@ in application logic while still allowing the effect to be scoped.+withGate ::+  Member (Scoped_ Gate) r =>+  InterpreterFor Gate r+withGate =+  scoped_
+ lib/Polysemy/Conc/Effect/Lock.hs view
@@ -0,0 +1,47 @@+-- |Lock effect, Internal+module Polysemy.Conc.Effect.Lock where++-- |An exclusive lock or mutex, protecting a region from concurrent access.+data Lock :: Effect where+  -- |Run an action if the lock is available, block otherwise.+  Lock :: m a -> Lock m a+  -- |Run the second action if the lock is available, or the first action otherwise.+  LockOr :: m a -> m a -> Lock m a++makeSem_ ''Lock++-- |Run an action if the lock is available, block otherwise.+lock ::+  ∀ r a .+  Member Lock r =>+  Sem r a ->+  Sem r a++-- |Run an action if the lock is available, block otherwise.+lockOr ::+  ∀ r a .+  Member Lock r =>+  Sem r a ->+  Sem r a ->+  Sem r a++-- |Run an action if the lock is available, skip and return 'Nothing' otherwise.+lockOrSkip ::+  ∀ r a .+  Member Lock r =>+  Sem r a ->+  Sem r (Maybe a)+lockOrSkip ma =+  lockOr (pure Nothing) (Just <$> ma)+{-# inline lockOrSkip #-}++-- |Run an action if the lock is available, skip otherwise.+-- Return @()@.+lockOrSkip_ ::+  ∀ r a .+  Member Lock r =>+  Sem r a ->+  Sem r ()+lockOrSkip_ ma =+  lockOr unit (void ma)+{-# inline lockOrSkip_ #-}
lib/Polysemy/Conc/Effect/Mask.hs view
@@ -3,7 +3,7 @@ -- |Description: Mask Effect, Internal module Polysemy.Conc.Effect.Mask where -import Polysemy.Conc.Effect.Scoped (Scoped, scoped)+import Polysemy.Conc.Effect.Scoped (Scoped_, scoped_)  -- |Part of an effect abstracting 'Control.Exception.mask'. data RestoreMask :: Effect where@@ -19,34 +19,30 @@   Sem r a ->   Sem r a -newtype MaskResource resource =-  MaskResource { unMaskResource :: resource }--newtype UninterruptibleMaskResource resource =-  UninterruptibleMaskResource { unUninterruptibleMaskResource :: resource }+-- |Resource type for the scoped 'Mask' effect, wrapping the @restore@ callback passed in by 'Base.mask'.+newtype Restoration =+  Restoration { unRestoration :: ∀ a . IO a -> IO a }  -- |The scoped masking effect.-type Mask resource =-  Scoped (MaskResource resource) RestoreMask+type Mask =+  Scoped_ RestoreMask  -- |The scoped uninterruptible masking effect.-type UninterruptibleMask resource =-  Scoped (UninterruptibleMaskResource resource) RestoreMask+type UninterruptibleMask =+  Scoped_ RestoreMask  -- |Mark a region as masked.--- Uses the 'Scoped' pattern.+-- Uses the 'Scoped_' pattern. mask ::-  ∀ resource r .-  Member (Mask resource) r =>+  Member Mask r =>   InterpreterFor RestoreMask r mask =-  scoped @(MaskResource resource)+  scoped_  -- |Mark a region as uninterruptibly masked.--- Uses the 'Scoped' pattern.+-- Uses the 'Scoped_' pattern. uninterruptibleMask ::-  ∀ resource r .-  Member (UninterruptibleMask resource) r =>+  Member UninterruptibleMask r =>   InterpreterFor RestoreMask r uninterruptibleMask =-  scoped @(UninterruptibleMaskResource resource)+  scoped_
lib/Polysemy/Conc/Effect/Monitor.hs view
@@ -5,7 +5,7 @@  import Polysemy.Time (NanoSeconds) -import Polysemy.Conc.Effect.Scoped (Scoped, scoped)+import Polysemy.Conc.Effect.Scoped (Scoped_, scoped_)  -- |Marker type for the restarting action for 'Monitor'. data Restart =@@ -15,7 +15,7 @@ -- |Mark a region as being subject to intervention by a monitoring program. -- This can mean that a thread is repeatedly checking a condition and cancelling this region when it is unmet. -- A use case could be checking whether a remote service is available, or whether the system was suspended and resumed.--- This should be used in a 'Scoped' context, like 'withMonitor'.+-- This should be used in a 'Scoped_' context, like 'withMonitor'. data Monitor (action :: Type) :: Effect where   Monitor :: m a -> Monitor action m a @@ -28,19 +28,15 @@   Sem r a ->   Sem r a --- |Marker type for a 'Scoped' 'Monitor'.-newtype MonitorResource a =-  MonitorResource { unMonitorResource :: a }---- |Convenience alias for a 'Scoped' 'Monitor'.-type ScopedMonitor (resource :: Type) (action :: Type) =-  Scoped (MonitorResource resource) (Monitor action)+-- |Convenience alias for a 'Scoped_' 'Monitor'.+type ScopedMonitor (action :: Type) =+  Scoped_ (Monitor action)  -- |'Monitor' specialized to the 'Restart' action.-type RestartingMonitor (resource :: Type) =-  ScopedMonitor resource Restart+type RestartingMonitor =+  ScopedMonitor Restart --- |Resources for a 'Scoped' 'Monitor'.+-- |Resources for a 'Scoped_' 'Monitor'. data MonitorCheck r =   MonitorCheck {     interval :: NanoSeconds,@@ -49,16 +45,15 @@  -- |Start a region that can contain monitor-intervention regions. withMonitor ::-  ∀ resource action r .-  Member (ScopedMonitor resource action) r =>+  ∀ action r .+  Member (ScopedMonitor action) r =>   InterpreterFor (Monitor action) r withMonitor =-  scoped @(MonitorResource resource)+  scoped_  -- |Variant of 'withMonitor' that uses the 'Restart' strategy. restart ::-  ∀ resource r .-  Member (ScopedMonitor resource Restart) r =>+  Member (ScopedMonitor Restart) r =>   InterpreterFor (Monitor Restart) r restart =-  withMonitor @resource+  withMonitor
lib/Polysemy/Conc/Effect/Race.hs view
@@ -10,7 +10,7 @@ data Race :: Effect where   -- |Run both programs concurrently, returning the result of the faster one.   Race :: m a -> m b -> Race m (Either a b)-  -- |Run the fallback action if the given program doesn't finish within the specified interval.+  -- |Run the first action if the second action doesn't finish within the specified interval.   Timeout :: TimeUnit u => m a -> u -> m b -> Race m (Either a b)  makeSem_ ''Race
lib/Polysemy/Conc/Effect/Scoped.hs view
@@ -3,28 +3,149 @@ -- |Description: Scoped Effect, Internal module Polysemy.Conc.Effect.Scoped where --- |@Scoped@ transforms a program so that @effect@ is associated with a @resource@ within that program.--- This requires the interpreter for @effect@ to be parameterized by @resource@ and constructed for every program using--- @Scoped@ separately.+-- | @Scoped@ transforms a program so that an interpreter for @effect@ may+-- perform arbitrary actions, like resource management, before and after the+-- computation wrapped by a call to 'scoped' is executed. ----- An application for this is 'Polysemy.Conc.Events', in which each program using the effect 'Polysemy.Conc.Consume' is--- interpreted with its own copy of the event channel; or a database transaction, in which a transaction handle is--- created for the wrapped program and passed to the interpreter for the database effect.+-- /Note/: This effect has been merged to Polysemy and will be released there soon. ----- Resource creation is performed by the function passed to 'Polysemy.Conc.Interpreter.runScoped'.+-- An application for this is @Polysemy.Conc.Events@ from+-- <https://hackage.haskell.org/package/polysemy-conc>, in which each program+-- using the effect @Polysemy.Conc.Consume@ is interpreted with its own copy of+-- the event channel; or a database transaction, in which a transaction handle+-- is created for the wrapped program and passed to the interpreter for the+-- database effect. ----- The constructors are not intended to be used directly; the smart constructor 'scoped' is used like a local--- interpreter for @effect@.-data Scoped (resource :: Type) (effect :: Effect) :: Effect where-  Run :: ∀ resource effect m a . resource -> effect m a -> Scoped resource effect m a-  InScope :: ∀ resource effect m a . (resource -> m a) -> Scoped resource effect m a+-- For a longer exposition, see <https://www.tweag.io/blog/2022-01-05-polysemy-scoped/>.+-- Note that the interface has changed since the blog post was published: The+-- @resource@ parameter no longer exists.+--+-- Resource allocation is performed by a function passed to+-- 'Polysemy.Scoped.interpretScoped'.+--+-- The constructors are not intended to be used directly; the smart constructor+-- 'scoped' is used like a local interpreter for @effect@. 'scoped' takes an+-- argument of type @param@, which will be passed through to the interpreter, to+-- be used by the resource allocation function.+--+-- As an example, imagine an effect for writing lines to a file:+--+-- > data Write :: Effect where+-- >   Write :: Text -> Write m ()+-- > makeSem ''Write+--+-- If we now have the following requirements:+--+-- 1. The file should be opened and closed right before and after the part of+--    the program in which we write lines+-- 2. The file name should be specifiable at the point in the program where+--    writing begins+-- 3. We don't want to commit to IO, lines should be stored in memory when+--    running tests+--+-- Then we can take advantage of 'Scoped' to write this program:+--+-- > prog :: Member (Scoped FilePath Write) r => Sem r ()+-- > prog = do+-- >   scoped "file1.txt" do+-- >     write "line 1"+-- >     write "line 2"+-- >   scoped "file2.txt" do+-- >     write "line 1"+-- >     write "line 2"+--+-- Here 'scoped' creates a prompt for an interpreter to start allocating a+-- resource for @"file1.txt"@ and handling @Write@ actions using that resource.+-- When the 'scoped' block ends, the resource should be freed.+--+-- The interpreter may look like this:+--+-- > interpretWriteFile :: Members '[Resource, Embed IO] => InterpreterFor (Scoped FilePath Write) r+-- > interpretWriteFile =+-- >   interpretScoped allocator handler+-- >   where+-- >     allocator name use = bracket (openFile name WriteMode) hClose use+-- >     handler fileHandle (Write line) = embed (Text.hPutStrLn fileHandle line)+--+-- Essentially, the @bracket@ is executed at the point where @scoped@ was+-- called, wrapping the following block. When the second @scoped@ is executed,+-- another call to @bracket@ is performed.+--+-- The effect of this is that the operation that uses @Embed IO@ was moved from+-- the call site to the interpreter, while the interpreter may be executed at+-- the outermost layer of the app.+--+-- This makes it possible to use a pure interpreter for testing:+--+-- > interpretWriteOutput :: Member (Output (FilePath, Text)) r => InterpreterFor (Scoped FilePath Write) r+-- > interpretWriteOutput =+-- >   interpretScoped (\ name use -> use name) \ name -> \case+-- >     Write line -> output (name, line)+--+-- Here we simply pass the name to the interpreter in the resource allocation+-- function.+--+-- Now imagine that we drop requirement 2 from the initial list – we still want+-- the file to be opened and closed as late/early as possible, but the file name+-- is globally fixed. For this case, the @param@ type is unused, and the API+-- provides some convenience aliases to make your code more concise:+--+-- > prog :: Member (Scoped_ Write) r => Sem r ()+-- > prog = do+-- >   scoped_ do+-- >     write "line 1"+-- >     write "line 2"+-- >   scoped_ do+-- >     write "line 1"+-- >     write "line 2"+--+-- The type 'Scoped_' and the constructor 'scoped_' simply fix @param@ to @()@.+data Scoped (param :: Type) (effect :: Effect) :: Effect where+  Run :: ∀ param effect m a . effect m a -> Scoped param effect m a+  InScope :: ∀ param effect m a . param -> m a -> Scoped param effect m a --- |Constructor for 'Scoped', taking a nested program and transforming all instances of @effect@ to--- @Scoped resource effect@.+-- |A convenience alias for a scope without parameters.+type Scoped_ effect =+  Scoped () effect++-- | Constructor for 'Scoped', taking a nested program and transforming all+-- instances of @effect@ to @'Scoped' param effect@.+--+-- Please consult the documentation of 'Scoped' for details and examples. scoped ::-  ∀ resource effect r .-  Member (Scoped resource effect) r =>+  ∀ param effect r .+  Member (Scoped param effect) r =>+  param ->   InterpreterFor effect r-scoped main =-  send $ InScope @resource @effect \ resource ->-    transform @effect (Run resource) main+scoped param main =+  send $ InScope @param @effect param do+    transform @effect (Run @param) main+{-# inline scoped #-}++-- | Constructor for 'Scoped_', taking a nested program and transforming all+-- instances of @effect@ to @'Scoped_' effect@.+--+-- Please consult the documentation of 'Scoped' for details and examples.+scoped_ ::+  ∀ effect r .+  Member (Scoped_ effect) r =>+  InterpreterFor effect r+scoped_ = scoped ()+{-# inline scoped_ #-}++-- | Transform the parameters of a 'Scoped' program.+--+-- This allows incremental additions to the data passed to the interpreter, for+-- example to create an API that permits different ways of running an effect+-- with some fundamental parameters being supplied at scope creation and some+-- optional or specific parameters being selected by the user downstream.+rescope ::+  ∀ param0 param1 effect r .+  Member (Scoped param1 effect) r =>+  (param0 -> param1) ->+  InterpreterFor (Scoped param0 effect) r+rescope fp =+  transform \case+    Run e          -> Run @param1 e+    InScope p main -> InScope (fp p) main+{-# inline rescope #-}
+ lib/Polysemy/Conc/Effect/Semaphore.hs view
@@ -0,0 +1,24 @@+-- |Semaphore effect, Internal.+module Polysemy.Conc.Effect.Semaphore where++-- |This effect abstracts over the concept of a quantity semaphore, a concurrency primitive that contains a number of+-- slots that can be acquired and released.+data Semaphore :: Effect where+  -- |Wait until a slot is available, then acquire it.+  Wait :: Semaphore m ()+  -- |Release a slot.+  Signal :: Semaphore m ()++makeSem_ ''Semaphore++-- |Wait until a slot is available, then acquire it.+wait ::+  ∀ r .+  Member Semaphore r =>+  Sem r ()++-- |Release a slot.+signal ::+  ∀ r .+  Member Semaphore r =>+  Sem r ()
lib/Polysemy/Conc/Effect/Sync.hs view
@@ -1,10 +1,10 @@ {-# options_haddock prune #-} --- |Description: Sync effect+-- |Description: Sync effect, Internal. module Polysemy.Conc.Effect.Sync where  import Polysemy.Time (TimeUnit)-import Polysemy.Conc.Effect.Scoped (Scoped)+import Polysemy.Conc.Effect.Scoped (Scoped_)  -- |Abstracts an 'Control.Concurrent.MVar'. --@@ -36,16 +36,13 @@   PutBlock :: d -> Sync d m ()   -- |Write the variable, waiting until it is writable or the timeout has expired.   PutWait :: TimeUnit u => u -> d -> Sync d m Bool-  -- |Write the variable, returning 'False' immmediately if no value was available.+  -- |Write the variable, returning 'False' immmediately if a value was available.   PutTry :: d -> Sync d m Bool   -- |Indicate whether the variable is empty.   Empty :: Sync d m Bool  makeSem ''Sync -newtype SyncResources a =-  SyncResources { unSyncResources :: a }- -- |Convenience alias.-type ScopedSync res a =-  Scoped (SyncResources res) (Sync a)+type ScopedSync a =+  Scoped_ (Sync a)
lib/Polysemy/Conc/Events.hs view
@@ -1,27 +1,188 @@ -- |Description: Events Combinators module Polysemy.Conc.Events where +import Polysemy.Conc.Async (withAsync_) import qualified Polysemy.Conc.Effect.Events as Events+import Polysemy.Conc.Effect.Events (Consume)+import Polysemy.Conc.Effect.Gate (Gate, Gates, gate, signal, withGate)+import Polysemy.Conc.Effect.Race (Race)+import Polysemy.Conc.Effect.Scoped (Scoped_) import Polysemy.Conc.Interpreter.Events (EventConsumer) +-- |Create a new scope for 'Polysemy.Conc.Events', causing the nested program to get its own copy of the event stream.+--+-- Calls 'signal' before running the argument to ensure that 'Events.subscribe' has finished creating a channel, for use+-- with asynchronous execution.+subscribeGated ::+  ∀ e r .+  Members [EventConsumer e, Gate] r =>+  InterpreterFor (Consume e) r+subscribeGated action =+  Events.subscribe @e do+    signal+    action++-- |Create a new scope for 'Polysemy.Conc.Events', causing the nested program to get its own copy of the event stream.+--+-- Executes in a new thread, ensuring that the main thread blocks until 'Events.subscribe' has finished creating a+-- channel.+subscribeAsync ::+  ∀ e r a .+  Members [EventConsumer e, Scoped_ Gate, Resource, Race, Async] r =>+  Sem (Consume e : r) () ->+  Sem r a ->+  Sem r a+subscribeAsync consumer ma =+  withGate $ withAsync_ (subscribeGated @_ (raiseUnder @Gate consumer)) do+    gate+    raise @Gate ma++-- |Pull repeatedly from 'Polysemy.Conc.Consume', passing the event to the supplied callback.+-- Stop when the action returns @False@.+consumeWhile ::+  Member (Consume e) r =>+  (e -> Sem r Bool) ->+  Sem r ()+consumeWhile action =+  spin+  where+    spin =+      whenM (action =<< Events.consume) spin+ -- |Pull repeatedly from the 'Polysemy.Conc.Events' channel, passing the event to the supplied callback. -- Stop when the action returns @False@. subscribeWhile ::-  ∀ e token r .-  Member (EventConsumer token e) r =>+  ∀ e r .+  Member (EventConsumer e) r =>   (e -> Sem r Bool) ->   Sem r () subscribeWhile action =-  Events.subscribe @e @token spin-  where-    spin =-      whenM (raise . action =<< Events.consume) spin+  Events.subscribe @e (consumeWhile (raise . action))  -- |Pull repeatedly from the 'Polysemy.Conc.Events' channel, passing the event to the supplied callback.+-- Stop when the action returns @False@.+--+-- Signals the caller that the channel was successfully subscribed to using the 'Gate' effect.+subscribeWhileGated ::+  ∀ e r .+  Members [EventConsumer e, Gate] r =>+  (e -> Sem r Bool) ->+  Sem r ()+subscribeWhileGated action =+  subscribeGated @e do+    consumeWhile (raise . action)++-- |Start a new thread that pulls repeatedly from the 'Polysemy.Conc.Events' channel, passing the event to the supplied+-- callback and stops when the action returns @False@.+subscribeWhileAsync ::+  ∀ e r a .+  Members [EventConsumer e, Gates, Resource, Race, Async] r =>+  (e -> Sem (Consume e : r) Bool) ->+  Sem r a ->+  Sem r a+subscribeWhileAsync action =+  subscribeAsync @e (consumeWhile action)++-- |Pull repeatedly from 'Polysemy.Conc.Consume', passing the event to the supplied callback.+consumeLoop ::+  Member (Consume e) r =>+  (e -> Sem r ()) ->+  Sem r ()+consumeLoop action =+  forever (action =<< Events.consume)++-- |Pull repeatedly from the 'Polysemy.Conc.Events' channel, passing the event to the supplied callback. subscribeLoop ::-  ∀ e token r .-  Member (EventConsumer token e) r =>+  ∀ e r .+  Member (EventConsumer e) r =>   (e -> Sem r ()) ->   Sem r () subscribeLoop action =-  Events.subscribe @e @token (forever (raise . action =<< Events.consume))+  Events.subscribe @e (consumeLoop (raise . action))++-- |Pull repeatedly from the 'Polysemy.Conc.Events' channel, passing the event to the supplied callback.+--+-- Signals the caller that the channel was successfully subscribed to using the 'Gate' effect.+subscribeLoopGated ::+  ∀ e r .+  Members [EventConsumer e, Gate] r =>+  (e -> Sem r ()) ->+  Sem r ()+subscribeLoopGated action =+  subscribeGated @e do+    consumeLoop (raise . action)++-- |Start a new thread that pulls repeatedly from the 'Polysemy.Conc.Events' channel, passing the event to the supplied+-- callback.+subscribeLoopAsync ::+  ∀ e r a .+  Members [EventConsumer e, Gates, Resource, Race, Async] r =>+  (e -> Sem (Consume e : r) ()) ->+  Sem r a ->+  Sem r a+subscribeLoopAsync action =+  subscribeAsync @e (consumeLoop action)++-- |Block until a value matching the predicate has been returned by 'Polysemy.Conc.Consume'.+consumeFind ::+  ∀ e r .+  Member (Consume e) r =>+  (e -> Sem r Bool) ->+  Sem r e+consumeFind f =+  spin+  where+    spin = do+      e <- Events.consume+      ifM (f e) (pure e) spin++-- |Block until a value matching the predicate has been published to the 'Polysemy.Conc.Events' channel.+subscribeFind ::+  ∀ e r .+  Member (EventConsumer e) r =>+  (e -> Sem (Consume e : r) Bool) ->+  Sem r e+subscribeFind f =+  Events.subscribe @e (consumeFind f)++-- |Return the first value returned by 'Polysemy.Conc.Consume' for which the function produces 'Just'.+consumeFirstJust ::+  ∀ e a r .+  Member (Consume e) r =>+  (e -> Sem r (Maybe a)) ->+  Sem r a+consumeFirstJust f =+  spin+  where+    spin = do+      e <- Events.consume+      maybe spin pure =<< f e++-- |Return the first value published to the 'Polysemy.Conc.Events' channel for which the function produces 'Just'.+subscribeFirstJust ::+  ∀ e a r .+  Member (EventConsumer e) r =>+  (e -> Sem (Consume e : r) (Maybe a)) ->+  Sem r a+subscribeFirstJust f =+  Events.subscribe @e (consumeFirstJust f)++-- |Block until the specified value has been returned by 'Polysemy.Conc.Consume'.+consumeElem ::+  ∀ e r .+  Eq e =>+  Member (Consume e) r =>+  e ->+  Sem r ()+consumeElem target =+  void (consumeFind (pure . (target ==)))++-- |Block until the specified value has been published to the 'Polysemy.Conc.Events' channel.+subscribeElem ::+  ∀ e r .+  Eq e =>+  Member (EventConsumer e) r =>+  e ->+  Sem r ()+subscribeElem target =+  Events.subscribe @e (consumeElem target)
+ lib/Polysemy/Conc/Gate.hs view
@@ -0,0 +1,10 @@+{-# options_haddock prune #-}++-- |Description: API for the 'Gate' effect+module Polysemy.Conc.Gate (+  module Polysemy.Conc.Effect.Gate,+  module Polysemy.Conc.Interpreter.Gate,+) where++import Polysemy.Conc.Effect.Gate+import Polysemy.Conc.Interpreter.Gate
lib/Polysemy/Conc/Interpreter/Events.hs view
@@ -7,35 +7,23 @@  import Polysemy.Conc.Async (withAsync_) import qualified Polysemy.Conc.Effect.Events as Events-import Polysemy.Conc.Effect.Events (Consume, EventResource (EventResource), Events)+import Polysemy.Conc.Effect.Events (Consume, Events) import Polysemy.Conc.Effect.Race (Race)-import Polysemy.Conc.Effect.Scoped (Scoped)+import Polysemy.Conc.Effect.Scoped (Scoped_) import Polysemy.Conc.Interpreter.Scoped (runScopedAs) --- |Convenience alias for the default 'Events' that uses an 'OutChan'.-type ChanEvents e =-  Events (OutChan e) e---- |Convenience alias for the default 'EventResource' that uses an 'OutChan'.-type EventChan e =-  EventResource (OutChan e)- -- |Convenience alias for the consumer effect.-type EventConsumer token e =-  Scoped (EventResource token) (Consume e)---- |Convenience alias for the consumer effect using the default implementation.-type ChanConsumer e =-  Scoped (EventChan e) (Consume e)+type EventConsumer e =+  Scoped_ (Consume e)  -- |Interpret 'Consume' by reading from an 'OutChan'. -- Used internally by 'interpretEventsChan', not safe to use directly. interpretConsumeChan ::   ∀ e r .   Member (Embed IO) r =>-  EventChan e ->+  OutChan e ->   InterpreterFor (Consume e) r-interpretConsumeChan (EventResource chan) =+interpretConsumeChan chan =   interpret \case     Events.Consume ->       embed (readChan chan)@@ -47,15 +35,15 @@   ∀ e r .   Member (Embed IO) r =>   InChan e ->-  InterpreterFor (Events (OutChan e) e) r+  InterpreterFor (Events e) r interpretEventsInChan inChan =   interpret \case     Events.Publish e ->       void (embed (tryWriteChan inChan e))  -- |Interpret 'Events' and 'Consume' together by connecting them to the two ends of an unagi channel.--- 'Consume' is only interpreted in a 'Scoped' manner, ensuring that a new duplicate of the channel is created so that--- all consumers see all events (from the moment they are connected).+-- 'Consume' is only interpreted in a 'Polysemy.Conc.Scoped' manner, ensuring that a new duplicate of the channel is+-- created so that all consumers see all events (from the moment they are connected). -- -- This should be used in conjunction with 'Polysemy.Conc.subscribe': --@@ -71,8 +59,8 @@ interpretEventsChan ::   ∀ e r .   Members [Resource, Race, Async, Embed IO] r =>-  InterpretersFor [Events (OutChan e) e, ChanConsumer e] r+  InterpretersFor [Events e, EventConsumer e] r interpretEventsChan sem = do   (inChan, outChan) <- embed (newChan @e 64)   withAsync_ (forever (embed (readChan outChan))) do-    runScopedAs (EventResource <$> embed (dupChan inChan)) interpretConsumeChan (interpretEventsInChan inChan sem)+    runScopedAs (const (embed (dupChan inChan))) interpretConsumeChan (interpretEventsInChan inChan sem)
+ lib/Polysemy/Conc/Interpreter/Gate.hs view
@@ -0,0 +1,34 @@+-- |Gate interpreters, Internal+module Polysemy.Conc.Interpreter.Gate where++import Polysemy.Conc.Effect.Gate (Gate (Gate, Signal))+import Polysemy.Conc.Effect.Scoped (Scoped_)+import Polysemy.Conc.Interpreter.Scoped (interpretScopedAs)++-- |Interpret 'Gate' with an 'MVar'.+interpretGate ::+  ∀ r .+  Member (Embed IO) r =>+  InterpreterFor Gate r+interpretGate sem = do+  mv <- embed newEmptyMVar+  int mv sem+  where+    int :: MVar () -> InterpreterFor Gate r+    int mv =+      interpret \case+        Signal ->+          void (embed (tryPutMVar mv ()))+        Gate ->+          embed (readMVar mv)++-- |Interpret @'Scoped_' 'Gate'@ with an @'MVar' ()@.+interpretGates ::+  Member (Embed IO) r =>+  InterpreterFor (Scoped_ Gate) r+interpretGates =+  interpretScopedAs @(MVar ()) (const (embed newEmptyMVar)) \ mv -> \case+    Signal ->+      void (embed (tryPutMVar mv ()))+    Gate ->+      embed (readMVar mv)
+ lib/Polysemy/Conc/Interpreter/Lock.hs view
@@ -0,0 +1,115 @@+{-# options_haddock prune #-}++-- |Lock interpreters, Internal+module Polysemy.Conc.Interpreter.Lock where++import Control.Concurrent (ThreadId, myThreadId)++import Polysemy.Conc.Effect.Lock (Lock (Lock, LockOr))+import Polysemy.Conc.Effect.Mask (Mask, mask, restore)+import Polysemy.Conc.Effect.Race (Race)+import qualified Polysemy.Conc.Effect.Sync as Sync (putTry, takeBlock, takeTry)+import Polysemy.Conc.Effect.Sync (Sync)+import Polysemy.Conc.Interpreter.Sync (interpretSyncAs)++currentThread ::+  Member (Embed IO) r =>+  Sem r ThreadId+currentThread =+  embed myThreadId++-- |Interpret 'Lock' by executing all actions unconditionally.+interpretLockPermissive ::+  InterpreterFor Lock r+interpretLockPermissive =+  interpretH \case+    Lock ma ->+      runTSimple ma+    LockOr _ ma ->+      runTSimple ma+{-# inline interpretLockPermissive #-}++lockOnDifferentThread ::+  ∀ f m r a .+  Members [Sync (), Resource, Race, Mask, Embed IO] r =>+  ThreadId ->+  m a ->+  (Sem (Lock : r) (f a) -> Sem (Lock : r) (f a)) ->+  Sem (WithTactics Lock f m r) (f a)+lockOnDifferentThread lockThread maI f = do+  thread <- currentThread+  ma <- runT maI+  raise $ interpretLockReentrantEntered thread do+    if thread == lockThread+    then ma+    else f ma+{-# inline lockOnDifferentThread #-}++enter ::+  ∀ f m r a .+  Members [Sync (), Resource, Race, Mask, Embed IO] r =>+  m a ->+  (Sem (Lock : r) (f a) -> Sem (Lock : r) (f a)) ->+  Sem (WithTactics Lock f m r) (f a)+enter maI f = do+  thread <- currentThread+  ma <- runT maI+  raise $ interpretLockReentrantEntered thread do+    f ma+{-# inline enter #-}++lockWait ::+  ∀ r a .+  Members [Sync (), Resource, Mask] r =>+  Sem r a ->+  Sem r a+lockWait ma =+  mask do+    Sync.takeBlock @()+    finally (restore (raise ma)) (Sync.putTry ())+{-# inline lockWait #-}++lockAlt ::+  ∀ r a .+  Members [Sync (), Resource, Mask] r =>+  Sem r a ->+  Sem r a ->+  Sem r a+lockAlt alt ma =+  mask do+    Sync.takeTry >>= \case+      Just () ->+        finally (restore (raise ma)) (Sync.putTry ())+      Nothing ->+        restore (raise alt)+{-# inline lockAlt #-}++-- |Subinterpreter for 'interpretLockReentrant' that checks whether the current thread is equal to the lock-acquiring+-- thread to allow reentry into the lock.+interpretLockReentrantEntered ::+  Members [Sync (), Resource, Race, Mask, Embed IO] r =>+  ThreadId ->+  InterpreterFor Lock r+interpretLockReentrantEntered lockThread =+  interpretH \case+    Lock maI ->+      lockOnDifferentThread lockThread maI (lockWait)+    LockOr altI maI -> do+      alt <- runT altI+      lockOnDifferentThread lockThread maI (lockAlt alt)+{-# inline interpretLockReentrantEntered #-}++-- |Interpret 'Lock' as a reentrant lock, allowing nested calls to 'Polysemy.Conc.lock' unless called from a different+-- thread (as in, @async@ was called in a higher-order action passed to 'Polysemy.Conc.lock'.)+interpretLockReentrant ::+  Members [Resource, Race, Mask, Embed IO] r =>+  InterpreterFor Lock r+interpretLockReentrant =+  interpretSyncAs () .+  reinterpretH \case+    Lock maI ->+      enter maI (lockWait)+    LockOr altI maI -> do+      alt <- runT altI+      enter maI (lockAlt alt)+{-# inline interpretLockReentrant #-}
lib/Polysemy/Conc/Interpreter/Mask.hs view
@@ -8,32 +8,27 @@  import Polysemy.Conc.Effect.Mask (   Mask,-  MaskResource (MaskResource),+  Restoration (Restoration),   RestoreMask (Restore),   UninterruptibleMask,-  UninterruptibleMaskResource (UninterruptibleMaskResource),   )-import Polysemy.Conc.Interpreter.Scoped (runScoped)---- |Resource type for the scoped 'Mask' effect, wrapping the @restore@ callback passed in by 'Base.mask'.-newtype Restoration =-  Restoration { unRestoration :: ∀ a . IO a -> IO a }+import Polysemy.Conc.Interpreter.Scoped (interpretScopedH, runScoped)  mask ::   Member (Final IO) r =>-  (MaskResource Restoration -> Sem r a) ->+  (Restoration -> Sem r a) ->   Sem r a mask f =   withWeavingToFinal @IO \ s lower _ ->-    Base.mask \ restore -> lower (f (MaskResource (Restoration restore)) <$ s)+    Base.mask \ restore -> lower (f (Restoration restore) <$ s)  uninterruptibleMask ::   Member (Final IO) r =>-  (UninterruptibleMaskResource Restoration -> Sem r a) ->+  (Restoration -> Sem r a) ->   Sem r a uninterruptibleMask f =   withWeavingToFinal @IO \ s lower _ ->-    Base.uninterruptibleMask \ restore -> lower (f (UninterruptibleMaskResource (Restoration restore)) <$ s)+    Base.uninterruptibleMask \ restore -> lower (f (Restoration restore) <$ s)  interpretRestoreMask ::   ∀ r .@@ -42,22 +37,31 @@   InterpreterFor RestoreMask r interpretRestoreMask (Restoration restore) =   interpretH \case-    Restore ma -> do-      let-        restoreSem m =-          withStrategicToFinal (restore <$> runS m)-      restoreSem (runTSimple ma)+    Restore ma ->+      withStrategicToFinal (restore <$> runS (runTSimple ma)) +-- |Interpret 'Mask' by sequencing the action without masking.+interpretMaskPure :: InterpreterFor Mask r+interpretMaskPure =+  interpretScopedH (const ($ ())) \ () -> \case+    Restore ma -> runTSimple ma+ -- |Interpret 'Mask' in 'IO'. interpretMaskFinal ::   Member (Final IO) r =>-  InterpreterFor (Mask Restoration) r+  InterpreterFor Mask r interpretMaskFinal =-  runScoped mask \ (MaskResource r) -> interpretRestoreMask r+  runScoped (const mask) \ r -> interpretRestoreMask r +-- |Interpret 'UninterruptibleMask' by sequencing the action without masking.+interpretUninterruptibleMaskPure :: InterpreterFor UninterruptibleMask r+interpretUninterruptibleMaskPure =+  interpretScopedH (const ($ ())) \ () -> \case+    Restore ma -> runTSimple ma+ -- |Interpret 'UninterruptibleMask' in 'IO'. interpretUninterruptibleMaskFinal ::   Member (Final IO) r =>-  InterpreterFor (UninterruptibleMask Restoration) r+  InterpreterFor UninterruptibleMask r interpretUninterruptibleMaskFinal =-  runScoped uninterruptibleMask \ (UninterruptibleMaskResource r) -> interpretRestoreMask r+  runScoped (const uninterruptibleMask) \ r -> interpretRestoreMask r
lib/Polysemy/Conc/Interpreter/Monitor.hs view
@@ -8,13 +8,7 @@ import Polysemy.Time (Time)  import Polysemy.Conc.Async (withAsync_)-import Polysemy.Conc.Effect.Monitor (-  Monitor (Monitor),-  MonitorCheck (MonitorCheck),-  MonitorResource (MonitorResource),-  RestartingMonitor,-  ScopedMonitor,-  )+import Polysemy.Conc.Effect.Monitor (Monitor (Monitor), MonitorCheck (MonitorCheck), RestartingMonitor, ScopedMonitor) import qualified Polysemy.Conc.Effect.Race as Race import Polysemy.Conc.Effect.Race (Race) import Polysemy.Conc.Interpreter.Scoped (runScoped, runScopedAs)@@ -29,9 +23,9 @@  interpretMonitorCancel ::   Members [Race, Async, Final IO] r =>-  MonitorResource CancelResource ->+  CancelResource ->   InterpreterFor (Monitor action) r-interpretMonitorCancel (MonitorResource CancelResource {..}) =+interpretMonitorCancel CancelResource {..} =   interpretH \case     Monitor ma ->       either (const (Base.throw MonitorCancel)) pure =<< Race.race (embedFinal @IO (readMVar signal)) (runTSimple ma)@@ -40,14 +34,14 @@   ∀ t d r a .   Members [Time t d, Resource, Async, Race, Final IO] r =>   MonitorCheck r ->-  (MonitorResource CancelResource -> Sem r a) ->+  (CancelResource -> Sem r a) ->   Sem r a monitorRestart (MonitorCheck interval check) use = do   sig <- embedFinal @IO newEmptyMVar   withAsync_ (Time.loop_ @t @d interval (check sig)) (spin sig)   where     spin sig = do-      let res = (MonitorResource (CancelResource sig))+      let res = (CancelResource sig)       void (embedFinal @IO (tryTakeMVar sig))       either (const (spin sig)) pure =<< errorToIOFinal @MonitorCancel (fromExceptionSem @MonitorCancel (raise (use res))) @@ -58,17 +52,17 @@   ∀ t d r .   Members [Time t d, Resource, Async, Race, Final IO] r =>   MonitorCheck r ->-  InterpreterFor (RestartingMonitor CancelResource) r+  InterpreterFor RestartingMonitor r interpretMonitorRestart check =-  runScoped (monitorRestart @t @d check) interpretMonitorCancel+  runScoped (const (monitorRestart @t @d check)) interpretMonitorCancel -interpretMonitorPure' :: MonitorResource () -> InterpreterFor (Monitor action) r+interpretMonitorPure' :: () -> InterpreterFor (Monitor action) r interpretMonitorPure' _ =   interpretH \case     Monitor ma ->       runTSimple ma  -- |Run 'Monitor' as a no-op.-interpretMonitorPure :: InterpreterFor (ScopedMonitor () action) r+interpretMonitorPure :: InterpreterFor (ScopedMonitor action) r interpretMonitorPure =-  runScopedAs (pure (MonitorResource ())) interpretMonitorPure'+  runScopedAs (const unit) interpretMonitorPure'
lib/Polysemy/Conc/Interpreter/Scoped.hs view
@@ -3,120 +3,321 @@ -- |Description: Scoped Interpreters, Internal module Polysemy.Conc.Interpreter.Scoped where -import Polysemy.Internal (Sem (Sem, runSem), liftSem)-import Polysemy.Internal.Index (InsertAtIndex)+import GHC.Err (errorWithoutStackTrace)+import Polysemy.Internal (Sem (Sem), hoistSem, liftSem, runSem)+import Polysemy.Internal.Sing (KnownList (singList)) import Polysemy.Internal.Tactics (liftT, runTactics)-import Polysemy.Internal.Union (Weaving (Weaving), decomp, hoist, injWeaving)+import Polysemy.Internal.Union (+  Union (Union),+  Weaving (Weaving),+  decomp,+  extendMembershipLeft,+  hoist,+  injWeaving,+  injectMembership,+  )+import Polysemy.Membership (ElemOf) import Polysemy.Resume (Stop, runStop, type (!!)) import Polysemy.Resume.Effect.Resumable (Resumable (Resumable))  import Polysemy.Conc.Effect.Scoped (Scoped (InScope, Run)) -interpretH' ::+interpretWeaving ::   ∀ e r .   (∀ x . Weaving e (Sem (e : r)) x -> Sem r x) ->   InterpreterFor e r-interpretH' h (Sem m) =+interpretWeaving h (Sem m) =   Sem \ k -> m $ decomp >>> \case     Right wav -> runSem (h wav) k-    Left g -> k $ hoist (interpretH' h) g+    Left g -> k (hoist (interpretWeaving h) g) +restack :: (∀ e . ElemOf e r -> ElemOf e r')+        -> Sem r a+        -> Sem r' a+restack n =+  hoistSem $ \ (Union pr wav) -> hoist (restack n) (Union (n pr) wav)+{-# inline restack #-} --- |Interpreter for 'Scoped', taking a @resource@ allocation function and a parameterized interpreter for the plain--- @effect@.------ @withResource@ is a callback function, allowing the user to acquire the resource for each program from other effects.+-- | Construct an interpreter for a higher-order effect wrapped in a 'Scoped',+-- given a resource allocation function and a parameterized handler for the+-- plain effect. ----- @scopedInterpreter@ is a regular interpreter that is called with the @resource@ argument produced by @scope@.--- /Note/: This function will be called for each action in the program, so if the interpreter allocates any resources,--- they will be scoped to a single action. Move them to @withResource@ instead.-runScoped ::-  ∀ resource effect r .-  (∀ x . (resource -> Sem r x) -> Sem r x) ->-  (resource -> InterpreterFor effect r) ->-  InterpreterFor (Scoped resource effect) r-runScoped withResource scopedInterpreter =-  run-  where-    run :: InterpreterFor (Scoped resource effect) r-    run =-      interpretH' \ (Weaving effect s wv ex ins) -> case effect of-        Run resource act ->-          scopedInterpreter resource (liftSem $ injWeaving $ Weaving act s (raise . run . wv) ex ins)-        InScope main ->-          ex <$> withResource \ resource -> run (wv (main resource <$ s))---- |Variant of 'runScoped' in which the resource allocator is a plain action.-runScopedAs ::-  ∀ resource effect r .-  Sem r resource ->-  (resource -> InterpreterFor effect r) ->-  InterpreterFor (Scoped resource effect) r-runScopedAs resource =-  runScoped \ f -> f =<< resource---- |Variant of 'runScoped' that takes a higher-order handler instead of an interpreter.+-- This combinator is analogous to 'interpretH' in that it allows the handler to+-- use the 'Tactical' environment and transforms the effect into other effects+-- on the stack. interpretScopedH ::-  ∀ resource effect r .-  (∀ x . (resource -> Sem r x) -> Sem r x) ->+  ∀ resource param effect r .+  -- | A callback function that allows the user to acquire a resource for each+  -- computation wrapped by 'Polysemy.Conc.scoped' using other effects, with an additional+  -- argument that contains the call site parameter passed to 'Polysemy.Conc.scoped'.+  (∀ x . param -> (resource -> Sem r x) -> Sem r x) ->+  -- | A handler like the one expected by 'interpretH' with an additional+  -- parameter that contains the @resource@ allocated by the first argument.   (∀ r0 x . resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r x) ->-  InterpreterFor (Scoped resource effect) r+  InterpreterFor (Scoped param effect) r interpretScopedH withResource scopedHandler =-  run+  go (errorWithoutStackTrace "top level run")   where-    run :: InterpreterFor (Scoped resource effect) r-    run =-      interpretH' \ (Weaving effect s wv ex ins) -> case effect of-        Run resource act ->-          ex <$> runTactics s (raise . run . wv) ins (run . wv) (scopedHandler resource act)-        InScope main ->-          ex <$> withResource \ resource -> run (wv (main resource <$ s))+    go :: resource -> InterpreterFor (Scoped param effect) r+    go resource =+      interpretWeaving \ (Weaving effect s wv ex ins) -> case effect of+        Run act ->+          ex <$> runTactics s (raise . go resource . wv) ins (go resource . wv)+            (scopedHandler resource act)+        InScope param main ->+          withResource param \ resource' -> ex <$> go resource' (wv (main <$ s))+{-# inline interpretScopedH #-} --- |Variant of 'runScoped' that takes a handler instead of an interpreter.+-- | Variant of 'interpretScopedH' that allows the resource acquisition function+-- to use 'Tactical'.+interpretScopedH' ::+  ∀ resource param effect r .+  (∀ e r0 x . param -> (resource -> Tactical e (Sem r0) r x) ->+    Tactical e (Sem r0) r x) ->+  (∀ r0 x .+    resource -> effect (Sem r0) x ->+    Tactical (Scoped param effect) (Sem r0) r x) ->+  InterpreterFor (Scoped param effect) r+interpretScopedH' withResource scopedHandler =+  go (errorWithoutStackTrace "top level run")+  where+    go :: resource -> InterpreterFor (Scoped param effect) r+    go resource =+      interpretH \case+        Run act ->+          scopedHandler resource act+        InScope param main ->+          withResource param \ resource' ->+            raise . go resource' =<< runT main+{-# inline interpretScopedH' #-}++-- | First-order variant of 'interpretScopedH'. interpretScoped ::-  ∀ resource effect r .-  (∀ x . (resource -> Sem r x) -> Sem r x) ->-  (∀ r0 x . resource -> effect (Sem r0) x -> Sem r x) ->-  InterpreterFor (Scoped resource effect) r+  ∀ resource param effect r .+  (∀ x . param -> (resource -> Sem r x) -> Sem r x) ->+  (∀ m x . resource -> effect m x -> Sem r x) ->+  InterpreterFor (Scoped param effect) r interpretScoped withResource scopedHandler =   interpretScopedH withResource \ r e -> liftT (scopedHandler r e)+{-# inline interpretScoped #-} --- |Variant of 'interpretScoped' in which the resource allocator is a plain action.+-- | Variant of 'interpretScoped' in which the resource allocator is a plain+-- action. interpretScopedAs ::-  ∀ resource effect r .-  Sem r resource ->-  (∀ r0 x . resource -> effect (Sem r0) x -> Sem r x) ->-  InterpreterFor (Scoped resource effect) r+  ∀ resource param effect r .+  (param -> Sem r resource) ->+  (∀ m x . resource -> effect m x -> Sem r x) ->+  InterpreterFor (Scoped param effect) r interpretScopedAs resource =-  interpretScoped \ f -> f =<< resource+  interpretScoped \ p use -> use =<< resource p+{-# inline interpretScopedAs #-} +-- | Higher-order interpreter for 'Scoped' that allows the handler to use+-- additional effects that are interpreted by the resource allocator.+--+-- /Note/: It is necessary to specify the list of local interpreters with a type+-- application; GHC won't be able to figure them out from the type of+-- @withResource@.+--+-- As an example for a higher order effect, consider a mutexed concurrent state+-- effect, where an effectful function may lock write access to the state while+-- making it still possible to read it:+--+-- > data MState s :: Effect where+-- >   MState :: (s -> m (s, a)) -> MState s m a+-- >   MRead :: MState s m s+-- >+-- > makeSem ''MState+--+-- We can now use an 'Polysemy.AtomicState.AtomicState' to store the current+-- value and lock write access with an @MVar@. Since the state callback is+-- effectful, we need a higher order interpreter:+--+-- > withResource ::+-- >   Member (Embed IO) r =>+-- >   s ->+-- >   (MVar () -> Sem (AtomicState s : r) a) ->+-- >   Sem r a+-- > withResource initial use = do+-- >   tv <- embed (newTVarIO initial)+-- >   lock <- embed (newMVar ())+-- >   runAtomicStateTVar tv $ use lock+-- >+-- > interpretMState ::+-- >   ∀ s r .+-- >   Members [Resource, Embed IO] r =>+-- >   InterpreterFor (Scoped s (MState s)) r+-- > interpretMState =+-- >   interpretScopedWithH @'[AtomicState s] withResource \ lock -> \case+-- >     MState f ->+-- >       bracket_ (embed (takeMVar lock)) (embed (tryPutMVar lock ())) do+-- >         s0 <- atomicGet+-- >         res <- runTSimple (f s0)+-- >         Inspector ins <- getInspectorT+-- >         for_ (ins res) \ (s, _) -> atomicPut s+-- >         pure (snd <$> res)+-- >     MRead ->+-- >       liftT atomicGet+interpretScopedWithH ::+  ∀ extra resource param effect r r1 .+  r1 ~ (extra ++ r) =>+  KnownList extra =>+  (∀ x . param -> (resource -> Sem r1 x) -> Sem r x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r1 x) ->+  InterpreterFor (Scoped param effect) r+interpretScopedWithH withResource scopedHandler =+  interpretWeaving \case+    Weaving (InScope param main) s wv ex _ ->+      ex <$> withResource param \ resource -> inScope resource $+        restack+          (injectMembership+           (singList @'[Scoped param effect])+           (singList @extra)) $ wv (main <$ s)+    _ ->+      errorWithoutStackTrace "top level Run"+  where+    inScope :: resource -> InterpreterFor (Scoped param effect) r1+    inScope resource =+      interpretWeaving \case+        Weaving (InScope param main) s wv ex _ ->+          restack (extendMembershipLeft (singList @extra))+            (ex <$> withResource param \resource' ->+                inScope resource' (wv (main <$ s)))+        Weaving (Run act) s wv ex ins ->+          ex <$> runTactics s (raise . inScope resource . wv) ins (inScope resource . wv)+            (scopedHandler resource act)+{-# inline interpretScopedWithH #-}++-- | First-order variant of 'interpretScopedWithH'.+--+-- /Note/: It is necessary to specify the list of local interpreters with a type+-- application; GHC won't be able to figure them out from the type of+-- @withResource@:+--+-- > data SomeAction :: Effect where+-- >   SomeAction :: SomeAction m ()+-- >+-- > foo :: InterpreterFor (Scoped () SomeAction) r+-- > foo =+-- >   interpretScopedWith @[Reader Int, State Bool] localEffects \ () -> \case+-- >     SomeAction -> put . (> 0) =<< ask @Int+-- >   where+-- >     localEffects () use = evalState False (runReader 5 (use ()))+interpretScopedWith ::+  ∀ extra param resource effect r r1 .+  r1 ~ (extra ++ r) =>+  KnownList extra =>+  (∀ x . param -> (resource -> Sem r1 x) -> Sem r x) ->+  (∀ m x . resource -> effect m x -> Sem r1 x) ->+  InterpreterFor (Scoped param effect) r+interpretScopedWith withResource scopedHandler =+  interpretScopedWithH @extra withResource \ r e -> liftT (scopedHandler r e)+{-# inline interpretScopedWith #-}++-- | Variant of 'interpretScopedWith' in which no resource is used and the+-- resource allocator is a plain interpreter.+-- This is useful for scopes that only need local effects, but no resources in+-- the handler.+--+-- See the /Note/ on 'interpretScopedWithH'.+interpretScopedWith_ ::+  ∀ extra param effect r r1 .+  r1 ~ (extra ++ r) =>+  KnownList extra =>+  (∀ x . param -> Sem r1 x -> Sem r x) ->+  (∀ m x . effect m x -> Sem r1 x) ->+  InterpreterFor (Scoped param effect) r+interpretScopedWith_ withResource scopedHandler =+  interpretScopedWithH @extra (\ p f -> withResource p (f ())) \ () e -> liftT (scopedHandler e)+{-# inline interpretScopedWith_ #-}++-- | Variant of 'interpretScoped' that uses another interpreter instead of a+-- handler.+--+-- This is mostly useful if you want to reuse an interpreter that you cannot+-- easily rewrite (like from another library). If you have full control over the+-- implementation, 'interpretScoped' should be preferred.+--+-- /Note/: The wrapped interpreter will be executed fully, including the+-- initializing code surrounding its handler, for each action in the program, so+-- if the interpreter allocates any resources, they will be scoped to a single+-- action. Move them to @withResource@ instead.+--+-- For example, consider the following interpreter for+-- 'Polysemy.AtomicState.AtomicState':+--+-- > atomicTVar :: Member (Embed IO) r => a -> InterpreterFor (AtomicState a) r+-- > atomicTVar initial sem = do+-- >   tv <- embed (newTVarIO initial)+-- >   runAtomicStateTVar tv sem+--+-- If this interpreter were used for a scoped version of @AtomicState@ like+-- this:+--+-- > runScoped (\ initial use -> use initial) \ initial -> atomicTVar initial+--+-- Then the @TVar@ would be created every time an @AtomicState@ action is run,+-- not just when entering the scope.+--+-- The proper way to implement this would be to rewrite the resource allocation:+--+-- > runScoped (\ initial use -> use =<< embed (newTVarIO initial)) runAtomicStateTVar+runScoped ::+  ∀ resource param effect r .+  (∀ x . param -> (resource -> Sem r x) -> Sem r x) ->+  (resource -> InterpreterFor effect r) ->+  InterpreterFor (Scoped param effect) r+runScoped withResource scopedInterpreter =+  go (errorWithoutStackTrace "top level run")+  where+    go :: resource -> InterpreterFor (Scoped param effect) r+    go resource =+      interpretWeaving \ (Weaving effect s wv ex ins) -> case effect of+        Run act ->+          scopedInterpreter resource+            $ liftSem $ injWeaving $ Weaving act s (raise . go resource . wv) ex ins+        InScope param main ->+          withResource param \ resource' -> ex <$> go resource' (wv (main <$ s))+{-# inline runScoped #-}++-- | Variant of 'runScoped' in which the resource allocator returns the resource+-- rather tnen calling a continuation.+runScopedAs ::+  ∀ resource param effect r .+  (param -> Sem r resource) ->+  (resource -> InterpreterFor effect r) ->+  InterpreterFor (Scoped param effect) r+runScopedAs resource = runScoped \ p use -> use =<< resource p+{-# inline runScopedAs #-}+ -- |Combined higher-order interpreter for 'Scoped' and 'Resumable'.--- This allows 'Stop' to be sent from within the resource allocator so that the consumer receives it.+-- This allows 'Stop' to be sent from within the resource allocator so that the consumer receives it, terminating the+-- entire scope. interpretScopedResumableH ::-  ∀ resource effect err r .-  (∀ x . (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) ->+  ∀ param resource effect err r .+  (∀ x . param -> (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) ->   (∀ r0 x . resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) ->-  InterpreterFor (Scoped resource effect !! err) r+  InterpreterFor (Scoped param effect !! err) r interpretScopedResumableH withResource scopedHandler =-  run+  run (errorWithoutStackTrace "top level run")   where-    run :: InterpreterFor (Scoped resource effect !! err) r-    run =-      interpretH' \ (Weaving (Resumable inner) s' dist' ex' ins') ->+    run :: resource -> InterpreterFor (Scoped param effect !! err) r+    run resource =+      interpretWeaving \ (Weaving (Resumable inner) s' dist' ex' ins') ->         case inner of           Weaving effect s dist ex ins -> do             let               handleScoped = \case-                Run resource act ->+                Run act ->                   scopedHandler resource act-                InScope main ->-                  raise (withResource \ resource -> Compose <$> raise (run (dist' (dist (main resource <$ s) <$ s'))))+                InScope param main ->+                  raise (withResource param \ resource' -> Compose <$> raise (run resource' (dist' (dist (main <$ s) <$ s'))))               tac =                 runTactics                 (Compose (s <$ s'))-                (raise . raise . run . fmap Compose . dist' . fmap dist . getCompose)+                (raise . raise . run resource . fmap Compose . dist' . fmap dist . getCompose)                 (ins <=< ins' . getCompose)-                (raise . run . fmap Compose . dist' . fmap dist . getCompose)+                (raise . run resource . fmap Compose . dist' . fmap dist . getCompose)                 (handleScoped effect)               exFinal = ex' . \case                 Right (Compose a) -> Right . ex <$> a@@ -124,128 +325,417 @@             exFinal <$> runStop tac  -- |Combined interpreter for 'Scoped' and 'Resumable'.--- This allows 'Stop' to be sent from within the resource allocator so that the consumer receives it.+-- This allows 'Stop' to be sent from within the resource allocator so that the consumer receives it, terminating the+-- entire scope. interpretScopedResumable ::-  ∀ resource effect err r .-  (∀ x . (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) ->+  ∀ param resource effect err r .+  (∀ x . param -> (resource -> Sem (Stop err : r) x) -> Sem (Stop err : r) x) ->   (∀ r0 x . resource -> effect (Sem r0) x -> Sem (Stop err : r) x) ->-  InterpreterFor (Scoped resource effect !! err) r+  InterpreterFor (Scoped param effect !! err) r interpretScopedResumable withResource scopedHandler =   interpretScopedResumableH withResource \ r e -> liftT (scopedHandler r e) -interpretScopedWithH ::-  ∀ extra resource effect r r1 .-  r1 ~ (extra ++ r) =>-  InsertAtIndex 1 '[Scoped resource effect] r1 r (Scoped resource effect : r1) extra =>-  (∀ x . (resource -> Sem r1 x) -> Sem r x) ->-  (∀ m x . resource -> effect m x -> Tactical effect m r1 x) ->-  InterpreterFor (Scoped resource effect) r-interpretScopedWithH withResource scopedHandler =-  interpretH' \case-    Weaving (InScope main) s wv ex _ ->-      ex <$> withResource \ resource -> inScope (insertAt @1 @extra (wv (main resource <$ s)))-    _ ->-      error "top level Run"-  where-    inScope :: InterpreterFor (Scoped resource effect) r1-    inScope =-      interpretH' \case-        Weaving (Run resource act) s wv ex ins ->-          ex <$> runTactics s (raise . inScope . wv) ins (inScope . wv) (scopedHandler resource act)-        _ ->-          error "nested InScope"--interpretScopedWith ::-  ∀ extra resource effect r r1 .-  r1 ~ (extra ++ r) =>-  InsertAtIndex 1 '[Scoped resource effect] r1 r (Scoped resource effect : r1) extra =>-  (∀ x . (resource -> Sem r1 x) -> Sem r x) ->-  (∀ m x . resource -> effect m x -> Sem r1 x) ->-  InterpreterFor (Scoped resource effect) r-interpretScopedWith withResource scopedHandler =-  interpretScopedWithH @extra withResource \ r e -> liftT (scopedHandler r e)--interpretScopedWith_ ::-  ∀ extra effect r r1 .-  r1 ~ (extra ++ r) =>-  InsertAtIndex 1 '[Scoped () effect] r1 r (Scoped () effect : r1) extra =>-  (∀ x . Sem r1 x -> Sem r x) ->-  (∀ m x . effect m x -> Sem r1 x) ->-  InterpreterFor (Scoped () effect) r-interpretScopedWith_ withResource scopedHandler =-  interpretScopedWithH @extra (\ f -> withResource (f ())) \ () e -> liftT (scopedHandler e)+-- |Combined interpreter for 'Scoped' and 'Resumable'.+-- This allows 'Stop' to be sent from within the resource allocator so that the consumer receives it, terminating the+-- entire scope.+-- In this variant, the resource allocator is a plain action.+interpretScopedResumable_ ::+  ∀ param resource effect err r .+  (param -> Sem (Stop err : r) resource) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Sem (Stop err : r) x) ->+  InterpreterFor (Scoped param effect !! err) r+interpretScopedResumable_ resource =+  interpretScopedResumable \ p use -> use =<< resource p +-- |Combined higher-order interpreter for 'Scoped' and 'Resumable' that allows the handler to use additional effects+-- that are interpreted by the resource allocator.+-- This allows 'Stop' to be sent from within the resource allocator so that the consumer receives it, terminating the+-- entire scope. interpretScopedResumableWithH ::-  ∀ extra resource effect err r r1 .+  ∀ extra param resource effect err r r1 .+  r1 ~ (extra ++ (Stop err : r)) =>   r1 ~ ((extra ++ '[Stop err]) ++ r) =>-  InsertAtIndex 1 '[Scoped resource effect !! err] r1 r (Scoped resource effect !! err : r1) (extra ++ '[Stop err]) =>-  (∀ x . (resource -> Sem r1 x) -> Sem (Stop err : r) x) ->+  KnownList extra =>+  KnownList (extra ++ '[Stop err]) =>+  (∀ x . param -> (resource -> Sem r1 x) -> Sem (Stop err : r) x) ->   (∀ r0 x . resource -> effect (Sem r0) x -> Tactical effect (Sem r0) r1 x) ->-  InterpreterFor (Scoped resource effect !! err) r+  InterpreterFor (Scoped param effect !! err) r interpretScopedResumableWithH withResource scopedHandler =-  run+  run (errorWithoutStackTrace "top level run")   where-    run :: InterpreterFor (Scoped resource effect !! err) r-    run =-      interpretH' \ (Weaving (Resumable inner) s' dist' ex' ins') ->+    run :: resource -> InterpreterFor (Scoped param effect !! err) r+    run resource =+      interpretWeaving \ (Weaving (Resumable inner) s' dist' ex' ins') ->         case inner of           Weaving effect s dist ex ins -> do             let               handleScoped = \case-                Run _ _ ->+                Run _ ->                   error "top level Run"-                InScope main ->-                  raise (withResource \ resource -> Compose <$> inScope (insertAt @1 @(extra ++ '[Stop err]) (dist' (dist (main resource <$ s) <$ s'))))+                InScope param main ->+                  raise $ withResource param \ resource' ->+                    Compose <$> inScope resource' (restack (injectMembership (singList @'[Scoped param effect !! err]) (singList @(extra ++ '[Stop err]))) (dist' (dist (main <$ s) <$ s')))               tac =                 runTactics                 (Compose (s <$ s'))-                (raise . raise . run . fmap Compose . dist' . fmap dist . getCompose)+                (raise . raise . run resource . fmap Compose . dist' . fmap dist . getCompose)                 (ins <=< ins' . getCompose)-                (raise . run . fmap Compose . dist' . fmap dist . getCompose)+                (raise . run resource . fmap Compose . dist' . fmap dist . getCompose)                 (handleScoped effect)               exFinal = ex' . \case                 Right (Compose a) -> Right . ex <$> a                 Left err -> Left err <$ s'             exFinal <$> runStop tac-    inScope :: InterpreterFor (Scoped resource effect !! err) r1-    inScope =-      interpretH' \ (Weaving (Resumable inner) s' dist' ex' ins') ->+    inScope :: resource -> InterpreterFor (Scoped param effect !! err) r1+    inScope resource =+      interpretWeaving \ (Weaving (Resumable inner) s' dist' ex' ins') ->         case inner of           Weaving effect s dist ex ins -> do             let               handleScoped = \case-                Run resource act ->+                Run act ->                   scopedHandler resource act-                InScope _ ->-                  error "nested InScope"+                InScope param main ->+                  raise $ restack (extendMembershipLeft (singList @extra)) $ withResource param \ resource' ->+                    Compose <$> inScope resource' (dist' (dist (main <$ s) <$ s'))               tac =                 runTactics                 (Compose (s <$ s'))-                (raise . inScope . fmap Compose . dist' . fmap dist . getCompose)+                (raise . inScope resource . fmap Compose . dist' . fmap dist . getCompose)                 (ins <=< ins' . getCompose)-                (inScope . fmap Compose . dist' . fmap dist . getCompose)+                (inScope resource . fmap Compose . dist' . fmap dist . getCompose)                 (handleScoped effect)               exFinal = ex' . \case                 Right (Compose a) -> Right . ex <$> a                 Left err -> Left err <$ s'             exFinal <$> runStop (raise tac) +-- |Combined interpreter for 'Scoped' and 'Resumable' that allows the handler to use additional effects that are+-- interpreted by the resource allocator.+-- This allows 'Stop' to be sent from within the resource allocator so that the consumer receives it, terminating the+-- entire scope. interpretScopedResumableWith ::-  ∀ extra resource effect err r r1 .+  ∀ extra param resource effect err r r1 .+  r1 ~ (extra ++ (Stop err : r)) =>   r1 ~ ((extra ++ '[Stop err]) ++ r) =>-  InsertAtIndex 1 '[Scoped resource effect !! err] r1 r (Scoped resource effect !! err : r1) (extra ++ '[Stop err]) =>-  (∀ x . (resource -> Sem r1 x) -> Sem (Stop err : r) x) ->+  KnownList extra =>+  KnownList (extra ++ '[Stop err]) =>+  (∀ x . param -> (resource -> Sem r1 x) -> Sem (Stop err : r) x) ->   (∀ r0 x . resource -> effect (Sem r0) x -> Sem r1 x) ->-  InterpreterFor (Scoped resource effect !! err) r+  InterpreterFor (Scoped param effect !! err) r interpretScopedResumableWith withResource scopedHandler =   interpretScopedResumableWithH @extra withResource \ r e -> liftT (scopedHandler r e) +-- |Combined interpreter for 'Scoped' and 'Resumable' that allows the handler to use additional effects that are+-- interpreted by the resource allocator.+-- This allows 'Stop' to be sent from within the resource allocator so that the consumer receives it, terminating the+-- entire scope.+-- In this variant, no resource is used and the allocator is a plain interpreter. interpretScopedResumableWith_ ::-  ∀ extra effect err r r1 .+  ∀ extra param effect err r r1 .+  r1 ~ (extra ++ (Stop err : r)) =>   r1 ~ ((extra ++ '[Stop err]) ++ r) =>-  InsertAtIndex 1 '[Scoped () effect !! err] r1 r (Scoped () effect !! err : r1) (extra ++ '[Stop err]) =>-  (∀ x . Sem r1 x -> Sem (Stop err : r) x) ->+  KnownList extra =>+  KnownList (extra ++ '[Stop err]) =>+  (∀ x . param -> Sem r1 x -> Sem (Stop err : r) x) ->   (∀ r0 x . effect (Sem r0) x -> Sem r1 x) ->-  InterpreterFor (Scoped () effect !! err) r-interpretScopedResumableWith_ withResource scopedHandler =-  interpretScopedResumableWith @extra (\ f -> withResource (f ())) (const scopedHandler)+  InterpreterFor (Scoped param effect !! err) r+interpretScopedResumableWith_ extra scopedHandler =+  interpretScopedResumableWith @extra (\ p f -> extra p (f ())) (const scopedHandler)++-- |Combined higher-order interpreter for 'Resumable' and 'Scoped'.+-- In this variant, only the handler may send 'Stop', but this allows resumption to happen on each action inside of the+-- scope.+interpretResumableScopedH ::+  ∀ param resource effect err r .+  (∀ x . param -> (resource -> Sem r x) -> Sem r x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r) x) ->+  InterpreterFor (Scoped param (effect !! err)) r+interpretResumableScopedH withResource scopedHandler =+  run (errorWithoutStackTrace "top level run")+  where+    run :: resource -> InterpreterFor (Scoped param (effect !! err)) r+    run resource =+      interpretWeaving \ (Weaving inner s' dist' ex' ins') -> case inner of+        Run (Resumable (Weaving effect s dist ex ins)) ->+          exFinal <$> runStop (tac (scopedHandler resource effect))+          where+            tac =+              runTactics+              (Compose (s <$ s'))+              (raise . raise . run resource . fmap Compose . dist' . fmap dist . getCompose)+              (ins <=< ins' . getCompose)+              (raise . run resource . fmap Compose . dist' . fmap dist . getCompose)+            exFinal = ex' . \case+              Right (Compose a) -> Right . ex <$> a+              Left err -> Left err <$ s'+        InScope param main ->+          ex' <$> withResource param \ resource' -> run resource' (dist' (main <$ s'))++-- |Combined interpreter for 'Resumable' and 'Scoped'.+-- In this variant, only the handler may send 'Stop', but this allows resumption to happen on each action inside of the+-- scope.+interpretResumableScoped ::+  ∀ param resource effect err r .+  (∀ x . param -> (resource -> Sem r x) -> Sem r x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Sem (Stop err : r) x) ->+  InterpreterFor (Scoped param (effect !! err)) r+interpretResumableScoped withResource scopedHandler =+  interpretResumableScopedH withResource \ r e -> liftT (scopedHandler r e)++-- |Combined interpreter for 'Resumable' and 'Scoped'.+-- In this variant:+-- - Only the handler may send 'Stop', but this allows resumption to happen on each action inside of the scope.+-- - The resource allocator is a plain action.+interpretResumableScoped_ ::+  ∀ param resource effect err r .+  (param -> Sem r resource) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Sem (Stop err : r) x) ->+  InterpreterFor (Scoped param (effect !! err)) r+interpretResumableScoped_ resource =+  interpretResumableScoped \ p use -> use =<< resource p++-- |Combined higher-order interpreter for 'Resumable' and 'Scoped' that allows the handler to use additional effects+-- that are interpreted by the resource allocator.+-- In this variant, only the handler may send 'Stop', but this allows resumption to happen on each action inside of the+-- scope.+interpretResumableScopedWithH ::+  ∀ extra param resource effect err r r1 .+  r1 ~ (extra ++ r) =>+  KnownList extra =>+  (∀ x . param -> (resource -> Sem r1 x) -> Sem r x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop err : r1) x) ->+  InterpreterFor (Scoped param (effect !! err)) r+interpretResumableScopedWithH withResource scopedHandler =+  interpretWeaving \case+    Weaving (InScope param main) s dist ex _ ->+      ex <$> withResource param \ resource' -> inScope resource' (restack (injectMembership (singList @'[Scoped param (effect !! err)]) (singList @extra)) (dist (main <$ s)))+    _ ->+      errorWithoutStackTrace "top level run"+  where+    inScope :: resource -> InterpreterFor (Scoped param (effect !! err)) r1+    inScope resource =+      interpretWeaving \case+        Weaving (Run (Resumable (Weaving effect s dist ex ins))) s' dist' ex' ins' ->+          exFinal <$> runStop (tac (scopedHandler resource effect))+          where+            tac =+              runTactics+              (Compose (s <$ s'))+              (raise . raise . inScope resource . fmap Compose . dist' . fmap dist . getCompose)+              (ins <=< ins' . getCompose)+              (raise . inScope resource . fmap Compose . dist' . fmap dist . getCompose)+            exFinal = ex' . \case+              Right (Compose a) -> Right . ex <$> a+              Left err -> Left err <$ s'+        Weaving (InScope param main) s wv ex _ ->+          restack (extendMembershipLeft (singList @extra)) (ex <$> withResource param \ resource' -> inScope resource' (wv (main <$ s)))++-- |Combined interpreter for 'Resumable' and 'Scoped' that allows the handler to use additional effects that are+-- interpreted by the resource allocator.+-- In this variant, only the handler may send 'Stop', but this allows resumption to happen on each action inside of the+-- scope.+interpretResumableScopedWith ::+  ∀ extra param resource effect err r r1 .+  r1 ~ (extra ++ r) =>+  KnownList extra =>+  (∀ x . param -> (resource -> Sem r1 x) -> Sem r x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Sem (Stop err : r1) x) ->+  InterpreterFor (Scoped param (effect !! err)) r+interpretResumableScopedWith withResource scopedHandler =+  interpretResumableScopedWithH @extra withResource \ r e -> liftT (scopedHandler r e)++-- |Combined interpreter for 'Resumable' and 'Scoped' that allows the handler to use additional effects that are+-- interpreted by the resource allocator.+-- In this variant:+-- - Only the handler may send 'Stop', but this allows resumption to happen on each action inside of the scope.+-- - No resource is used and the allocator is a plain interpreter.+interpretResumableScopedWith_ ::+  ∀ extra param effect err r r1 .+  r1 ~ (extra ++ r) =>+  KnownList extra =>+  (∀ x . param -> Sem r1 x -> Sem r x) ->+  (∀ r0 x . effect (Sem r0) x -> Sem (Stop err : r1) x) ->+  InterpreterFor (Scoped param (effect !! err)) r+interpretResumableScopedWith_ extra scopedHandler =+  interpretResumableScopedWith @extra @param @() @effect @err @r @r1 (\ p f -> extra p (f ())) (const scopedHandler)++-- |Combined higher-order interpreter for 'Resumable' and 'Scoped'.+-- In this variant, both the handler and the scope may send different errors via 'Stop', encoding the concept that the+-- resource allocation may fail to prevent the scope from being executed, and each individual scoped action may fail,+-- continuing the scope execution on resumption.+interpretScopedRH ::+  ∀ param resource effect eo ei r .+  (∀ x . param -> (resource -> Sem (Stop eo : r) x) -> Sem (Stop eo : r) x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop ei : r) x) ->+  InterpreterFor (Scoped param (effect !! ei) !! eo) r+interpretScopedRH withResource scopedHandler =+  run (errorWithoutStackTrace "top level run")+  where+    run :: resource -> InterpreterFor (Scoped param (effect !! ei) !! eo) r+    run resource =+      interpretWeaving \ (Weaving (Resumable (Weaving inner s' dist' ex' ins')) s'' dist'' ex'' ins'') -> case inner of+        Run (Resumable (Weaving effect s dist ex ins)) ->+          exFinal <$> runStop @ei (tac (scopedHandler resource effect))+          where+            tac =+              runTactics+              (Compose (Compose (s <$ s') <$ s''))+              (raise . raise . run resource . fmap Compose . fmap (fmap Compose) . dist'' . fmap dist' . fmap (fmap dist . getCompose) . getCompose)+              (ins <=< ins' . getCompose <=< ins'' . getCompose)+              (raise . run resource . fmap Compose . fmap (fmap Compose) . dist'' . fmap dist' . fmap (fmap dist . getCompose) . getCompose)+            exFinal = \case+              Right (Compose fffa) ->+                ex'' $ fffa <&> Right . \ (Compose ffa) ->+                  ex' (Right . ex <$> ffa)+              Left err ->+                ex'' (Right (ex' (Left err <$ s')) <$ s'')+        InScope param main -> do+          let+            inScope =+                raise (withResource param \ resource' -> Compose <$> raise (run resource' (dist'' (dist' (main <$ s') <$ s''))))+            tac =+              runTactics+              (Compose (s' <$ s''))+              (raise . raise . run resource . fmap Compose . dist'' . fmap dist' . getCompose)+              (ins' <=< ins'' . getCompose)+              (raise . run resource . fmap Compose . dist'' . fmap dist' . getCompose)+              inScope+            exFinal = ex'' . \case+              Right (Compose a) -> Right . ex' <$> a+              Left err -> Left err <$ s''+          exFinal <$> runStop tac++-- |Combined interpreter for 'Scoped' and 'Resumable'.+-- In this variant, both the handler and the scope may send different errors via 'Stop', encoding the concept that the+-- resource allocation may fail to prevent the scope from being executed, and each individual scoped action may fail,+-- continuing the scope execution on resumption.+interpretScopedR ::+  ∀ param resource effect eo ei r .+  (∀ x . param -> (resource -> Sem (Stop eo : r) x) -> Sem (Stop eo : r) x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Sem (Stop ei : r) x) ->+  InterpreterFor (Scoped param (effect !! ei) !! eo) r+interpretScopedR withResource scopedHandler =+  interpretScopedRH withResource \ r e -> liftT (scopedHandler r e)++-- |Combined interpreter for 'Scoped' and 'Resumable'.+-- In this variant:+-- - Both the handler and the scope may send different errors via 'Stop', encoding the concept that the+--   resource allocation may fail to prevent the scope from being executed, and each individual scoped action may fail,+--   continuing the scope execution on resumption.+-- - The resource allocator is a plain action.+interpretScopedR_ ::+  ∀ param resource effect eo ei r .+  (param -> Sem (Stop eo : r) resource) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Sem (Stop ei : r) x) ->+  InterpreterFor (Scoped param (effect !! ei) !! eo) r+interpretScopedR_ resource =+  interpretScopedR \ p use -> use =<< resource p++-- |Combined higher-order interpreter for 'Scoped' and 'Resumable' that allows the handler to use additional effects+-- that are interpreted by the resource allocator.+-- In this variant, both the handler and the scope may send different errors via 'Stop', encoding the concept that the+-- resource allocation may fail to prevent the scope from being executed, and each individual scoped action may fail,+-- continuing the scope execution on resumption.+interpretScopedRWithH ::+  ∀ extra param resource effect eo ei r r1 .+  r1 ~ (extra ++ Stop eo : r) =>+  r1 ~ ((extra ++ '[Stop eo]) ++ r) =>+  KnownList extra =>+  KnownList (extra ++ '[Stop eo]) =>+  (∀ x . param -> (resource -> Sem r1 x) -> Sem (Stop eo : r) x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (Stop ei : r1) x) ->+  InterpreterFor (Scoped param (effect !! ei) !! eo) r+interpretScopedRWithH withResource scopedHandler =+  run+  where+    run :: InterpreterFor (Scoped param (effect !! ei) !! eo) r+    run =+      interpretWeaving \ (Weaving (Resumable (Weaving inner s' dist' ex' ins')) s'' dist'' ex'' ins'') -> case inner of+        InScope param main -> do+            let+              ma =+                  raise $ withResource param \ resource ->+                    Compose <$> inScope resource (restack (injectMembership (singList @'[Scoped param (effect !! ei) !! eo]) (singList @(extra ++ '[Stop eo]))) (dist'' (dist' (main <$ s') <$ s'')))+              tac =+                runTactics+                (Compose (s' <$ s''))+                (raise . raise . run . fmap Compose . dist'' . fmap dist' . getCompose)+                (ins' <=< ins'' . getCompose)+                (raise . run . fmap Compose . dist'' . fmap dist' . getCompose)+                ma+              exFinal = ex'' . \case+                Right (Compose a) -> Right . ex' <$> a+                Left err -> Left err <$ s''+            exFinal <$> runStop tac+        _ ->+          error "top level Run"+    inScope :: resource -> InterpreterFor (Scoped param (effect !! ei) !! eo) r1+    inScope resource =+      interpretWeaving \ (Weaving (Resumable (Weaving inner s' dist' ex' ins')) s'' dist'' ex'' ins'') -> case inner of+        Run (Resumable (Weaving effect s dist ex ins)) ->+          exFinal <$> runStop @ei (tac (scopedHandler resource effect))+          where+            tac =+              runTactics+              (Compose (Compose (s <$ s') <$ s''))+              (raise . raise . inScope resource . fmap Compose . fmap (fmap Compose) . dist'' . fmap dist' . fmap (fmap dist . getCompose) . getCompose)+              (ins <=< ins' . getCompose <=< ins'' . getCompose)+              (raise . inScope resource . fmap Compose . fmap (fmap Compose) . dist'' . fmap dist' . fmap (fmap dist . getCompose) . getCompose)+            exFinal = \case+              Right (Compose fffa) ->+                ex'' $ fffa <&> Right . \ (Compose ffa) ->+                  ex' (Right . ex <$> ffa)+              Left err ->+                ex'' (Right (ex' (Left err <$ s')) <$ s'')+        InScope param main -> do+            let+              ma =+                raise $ restack (extendMembershipLeft (singList @(Stop eo : extra))) $ withResource param \ resource' ->+                  Compose <$> inScope resource' (dist'' (dist' (main <$ s') <$ s''))+              tac =+                runTactics+                (Compose (s' <$ s''))+                (raise . raise . inScope resource . fmap Compose . dist'' . fmap dist' . getCompose)+                (ins' <=< ins'' . getCompose)+                (raise . inScope resource . fmap Compose . dist'' . fmap dist' . getCompose)+                ma+              exFinal = ex'' . \case+                Right (Compose a) -> Right . ex' <$> a+                Left err -> Left err <$ s''+            exFinal <$> runStop tac++-- |Combined interpreter for 'Scoped' and 'Resumable' that allows the handler to use additional effects that are+-- interpreted by the resource allocator.+-- In this variant, both the handler and the scope may send different errors via 'Stop', encoding the concept that the+-- resource allocation may fail to prevent the scope from being executed, and each individual scoped action may fail,+-- continuing the scope execution on resumption.+interpretScopedRWith ::+  ∀ extra param resource effect eo ei r r1 .+  r1 ~ (extra ++ Stop eo : r) =>+  r1 ~ ((extra ++ '[Stop eo]) ++ r) =>+  KnownList extra =>+  KnownList (extra ++ '[Stop eo]) =>+  (∀ x . param -> (resource -> Sem r1 x) -> Sem (Stop eo : r) x) ->+  (∀ r0 x . resource -> effect (Sem r0) x -> Sem (Stop ei : r1) x) ->+  InterpreterFor (Scoped param (effect !! ei) !! eo) r+interpretScopedRWith withResource scopedHandler =+  interpretScopedRWithH @extra withResource \ r e -> liftT (scopedHandler r e)++-- |Combined interpreter for 'Scoped' and 'Resumable' that allows the handler to use additional effects that are+-- interpreted by the resource allocator.+-- - Both the handler and the scope may send different errors via 'Stop', encoding the concept that the+--   resource allocation may fail to prevent the scope from being executed, and each individual scoped action may fail,+--   continuing the scope execution on resumption.+-- - The resource allocator is a plain action.+interpretScopedRWith_ ::+  ∀ extra param effect eo ei r r1 .+  r1 ~ (extra ++ Stop eo : r) =>+  r1 ~ ((extra ++ '[Stop eo]) ++ r) =>+  KnownList extra =>+  KnownList (extra ++ '[Stop eo]) =>+  (∀ x . param -> Sem r1 x -> Sem (Stop eo : r) x) ->+  (∀ r0 x . effect (Sem r0) x -> Sem (Stop ei : r1) x) ->+  InterpreterFor (Scoped param (effect !! ei) !! eo) r+interpretScopedRWith_ extra scopedHandler =+  interpretScopedRWith @extra (\ p f -> extra p (f ())) (const scopedHandler)
+ lib/Polysemy/Conc/Interpreter/Semaphore.hs view
@@ -0,0 +1,55 @@+-- |Semaphore interpreters, Internal.+module Polysemy.Conc.Interpreter.Semaphore where++import Control.Concurrent (QSem, newQSem, signalQSem, waitQSem)+import Control.Concurrent.STM (atomically)+import Control.Concurrent.STM.TSem (TSem, newTSem, signalTSem, waitTSem)++import qualified Polysemy.Conc.Effect.Semaphore as Semaphore+import Polysemy.Conc.Effect.Semaphore (Semaphore)++-- |Interpret 'Semaphore' using the supplied 'QSem'.+interpretSemaphoreQWith ::+  Member (Embed IO) r =>+  QSem ->+  InterpreterFor Semaphore r+interpretSemaphoreQWith qsem =+  interpret \case+    Semaphore.Wait ->+      embed (waitQSem qsem)+    Semaphore.Signal ->+      embed (signalQSem qsem)+{-# inline interpretSemaphoreQWith #-}++-- |Interpret 'Semaphore' as a 'QSem'.+interpretSemaphoreQ ::+  Member (Embed IO) r =>+  Int ->+  InterpreterFor Semaphore r+interpretSemaphoreQ n sem = do+  qsem <- embed (newQSem n)+  interpretSemaphoreQWith qsem sem+{-# inline interpretSemaphoreQ #-}++-- |Interpret 'Semaphore' using the supplied 'TSem'.+interpretSemaphoreTWith ::+  Member (Embed IO) r =>+  TSem ->+  InterpreterFor Semaphore r+interpretSemaphoreTWith qsem =+  interpret \case+    Semaphore.Wait ->+      embed (atomically (waitTSem qsem))+    Semaphore.Signal ->+      embed (atomically (signalTSem qsem))+{-# inline interpretSemaphoreTWith #-}++-- |Interpret 'Semaphore' as a 'TSem'.+interpretSemaphoreT ::+  Member (Embed IO) r =>+  Integer ->+  InterpreterFor Semaphore r+interpretSemaphoreT n sem = do+  qsem <- embed (atomically (newTSem n))+  interpretSemaphoreTWith qsem sem+{-# inline interpretSemaphoreT #-}
lib/Polysemy/Conc/Interpreter/Stack.hs view
@@ -3,16 +3,19 @@ -- |Description: Convenience Interpreters for all Conc Effects, Internal module Polysemy.Conc.Interpreter.Stack where +import Polysemy.Conc.Effect.Gate (Gates) import Polysemy.Conc.Effect.Mask (Mask, UninterruptibleMask) import Polysemy.Conc.Effect.Race (Race)-import Polysemy.Conc.Interpreter.Mask (Restoration, interpretMaskFinal, interpretUninterruptibleMaskFinal)+import Polysemy.Conc.Interpreter.Gate (interpretGates)+import Polysemy.Conc.Interpreter.Mask (interpretMaskFinal, interpretUninterruptibleMaskFinal) import Polysemy.Conc.Interpreter.Race (interpretRace)  -- |A default basic stack with 'Final' for _polysemy-conc_. type ConcStack =   [-    UninterruptibleMask Restoration,-    Mask Restoration,+    UninterruptibleMask,+    Mask,+    Gates,     Race,     Async,     Resource,@@ -31,5 +34,6 @@   resourceToIOFinal .   asyncToIOFinal .   interpretRace .+  interpretGates .   interpretMaskFinal .   interpretUninterruptibleMaskFinal
lib/Polysemy/Conc/Interpreter/Sync.hs view
@@ -2,9 +2,9 @@ module Polysemy.Conc.Interpreter.Sync where  import Polysemy.Conc.Effect.Race (Race)-import Polysemy.Conc.Effect.Scoped (Scoped)+import Polysemy.Conc.Effect.Scoped (Scoped_) import qualified Polysemy.Conc.Effect.Sync as Sync-import Polysemy.Conc.Effect.Sync (Sync, SyncResources (SyncResources), unSyncResources)+import Polysemy.Conc.Effect.Sync (Sync) import Polysemy.Conc.Interpreter.Scoped (runScopedAs) import qualified Polysemy.Conc.Race as Race @@ -60,15 +60,15 @@ interpretScopedSync ::   ∀ d r .   Members [Resource, Race, Embed IO] r =>-  InterpreterFor (Scoped (SyncResources (MVar d)) (Sync d)) r+  InterpreterFor (Scoped_ (Sync d)) r interpretScopedSync =-  runScopedAs (SyncResources <$> embed newEmptyMVar) \ r -> interpretSyncWith (unSyncResources r)+  runScopedAs (const (embed newEmptyMVar)) \ r -> interpretSyncWith r  -- |Interpret 'Sync' for locally scoped use with an 'MVar' containing the specified value. interpretScopedSyncAs ::   ∀ d r .   Members [Resource, Race, Embed IO] r =>   d ->-  InterpreterFor (Scoped (SyncResources (MVar d)) (Sync d)) r+  InterpreterFor (Scoped_ (Sync d)) r interpretScopedSyncAs d =-  runScopedAs (SyncResources <$> embed (newMVar d)) \ r -> interpretSyncWith (unSyncResources r)+  runScopedAs (const (embed (newMVar d))) \ r -> interpretSyncWith r
lib/Polysemy/Conc/Queue.hs view
@@ -3,8 +3,10 @@ module Polysemy.Conc.Queue (   module Polysemy.Conc.Queue,   module Polysemy.Conc.Effect.Queue,+  module Polysemy.Conc.Data.QueueResult, ) where +import Polysemy.Conc.Data.QueueResult import qualified Polysemy.Conc.Data.QueueResult as QueueResult import qualified Polysemy.Conc.Effect.Queue as Queue import Polysemy.Conc.Effect.Queue (@@ -50,10 +52,18 @@ loop action =   loopOr (pure True) \ d -> True <$ action d --- |Read from a 'Queue' and convert the result to 'Maybe', returning 'Nothing' if there is no element available or the--- queue has been closed.+-- |Read from a 'Queue' and convert the result to 'Maybe', returning 'Nothing' if the queue has been closed, and+-- blocking until an element is available. readMaybe ::   Member (Queue d) r =>   Sem r (Maybe d) readMaybe =   resultToMaybe <$> read++-- |Read from a 'Queue' and convert the result to 'Maybe', returning 'Nothing' if there is no element available or the+-- queue has been closed.+tryReadMaybe ::+  Member (Queue d) r =>+  Sem r (Maybe d)+tryReadMaybe =+  resultToMaybe <$> tryRead
lib/Polysemy/Conc/Race.hs view
@@ -5,8 +5,9 @@  import qualified Polysemy.Conc.Effect.Race as Race import Polysemy.Conc.Effect.Race (Race)+import Polysemy.Resume (Stop, stop) --- |Specialization of 'Race.race' for the case where both thunks return the same type, obviating the need for 'Either'.+-- |Specialization of 'Race.race' for the case where both actions return the same type, obviating the need for 'Either'. race_ ::   Member Race r =>   Sem r a ->@@ -16,8 +17,8 @@   unify <$> Race.race ml mr {-# inline race_ #-} --- |Specialization of 'Race.timeout' for the case where the thunk return the same type as the fallback, obviating the--- need for 'Either'.+-- |Specialization of 'Race.timeout' for the case where the main action returns the same type as the fallback, obviating+-- the need for 'Either'. timeout_ ::   TimeUnit u =>   Member Race r =>@@ -41,7 +42,7 @@   Race.timeout (pure err) {-# inline timeoutAs #-} --- |Specialization of 'timeoutAs' for the case where the thunk return the same type as the fallback, obviating the+-- |Specialization of 'timeoutAs' for the case where the main action return the same type as the fallback, obviating the -- need for 'Either'. timeoutAs_ ::   TimeUnit u =>@@ -76,3 +77,14 @@   timeoutAs_ Nothing u (Just <$> ma) {-# inline timeoutMaybe #-} +-- |Variant of 'Race.timeout' that calls 'Stop' with the supplied error when the action times out.+timeoutStop ::+  TimeUnit u =>+  Members [Race, Stop err] r =>+  err ->+  u ->+  Sem r a ->+  Sem r a+timeoutStop err =+  timeout_ (stop err)+{-# inline timeoutStop #-}
+ lib/Polysemy/Conc/Semaphore.hs view
@@ -0,0 +1,11 @@+-- |A quantity semaphore effect.+module Polysemy.Conc.Semaphore (+  Semaphore,+  interpretSemaphoreQ,+  interpretSemaphoreT,+  signal,+  wait,+) where++import Polysemy.Conc.Effect.Semaphore (Semaphore, signal, wait)+import Polysemy.Conc.Interpreter.Semaphore (interpretSemaphoreQ, interpretSemaphoreT)
lib/Polysemy/Conc/Sync.hs view
@@ -10,23 +10,9 @@ import Polysemy.Time (Time, TimeUnit)  import Polysemy.Conc.Effect.Mask (Mask, mask, restore)-import Polysemy.Conc.Effect.Scoped (scoped)+import Polysemy.Conc.Effect.Scoped (scoped_) import qualified Polysemy.Conc.Effect.Sync as Sync-import Polysemy.Conc.Effect.Sync (-  ScopedSync,-  Sync,-  SyncResources,-  block,-  empty,-  putBlock,-  putTry,-  putWait,-  takeBlock,-  takeTry,-  takeWait,-  try,-  wait,-  )+import Polysemy.Conc.Effect.Sync  -- |Run an action repeatedly until the 'Sync' variable is available. whileEmpty ::@@ -57,13 +43,14 @@       whenM (not <$> Sync.empty @a) (Time.sleep @t @d interval *> spin)  -- |Run an action with a locally scoped 'Sync' variable.+-- -- This avoids a dependency on @'Embed' 'IO'@ in application logic while still allowing the variable to be scoped. withSync ::-  ∀ d res r .-  Member (ScopedSync res d) r =>+  ∀ d r .+  Member (ScopedSync d) r =>   InterpreterFor (Sync d) r withSync =-  scoped @(SyncResources res)+  scoped_  -- |Run the action @ma@ with an exclusive lock (mutex). -- When multiple threads call the action concurrently, only one is allowed to execute it at a time.@@ -94,12 +81,12 @@ -- Allows a value to be returned. -- Equivalent to 'Control.Concurrent.MVar.modifyMVar'. modify ::-  ∀ a b res r .-  Members [Sync a, Mask res, Resource] r =>+  ∀ a b r .+  Members [Sync a, Mask, Resource] r =>   (a -> Sem r (a, b)) ->   Sem r b modify m =-  mask @res do+  mask do     a <- takeBlock     (a', b) <- onException (restore (raise (m a))) (putBlock a)     b <$ putBlock a'@@ -109,12 +96,12 @@ -- Does not allow a value to be returned. -- Equivalent to 'Control.Concurrent.MVar.modifyMVar_'. modify_ ::-  ∀ a res r .-  Members [Sync a, Mask res, Resource] r =>+  ∀ a r .+  Members [Sync a, Mask, Resource] r =>   (a -> Sem r a) ->   Sem r () modify_ m =-  mask @res do+  mask do     a <- takeBlock     a' <- onException (restore (raise (m a))) (putBlock a)     putBlock a'@@ -124,12 +111,12 @@ -- Allows a value to be returned. -- Equivalent to 'Control.Concurrent.MVar.modifyMVarMasked'. modifyMasked ::-  ∀ a b res r .-  Members [Sync a, Mask res, Resource] r =>+  ∀ a b r .+  Members [Sync a, Mask, Resource] r =>   (a -> Sem r (a, b)) ->   Sem r b modifyMasked m =-  mask @res do+  mask do     a <- takeBlock     (a', b) <- onException (raise (m a)) (putBlock a)     b <$ putBlock a'@@ -139,12 +126,12 @@ -- Does not allow a value to be returned. -- Equivalent to 'Control.Concurrent.MVar.modifyMVarMasked_'. modifyMasked_ ::-  ∀ a res r .-  Members [Sync a, Mask res, Resource] r =>+  ∀ a r .+  Members [Sync a, Mask, Resource] r =>   (a -> Sem r a) ->   Sem r () modifyMasked_ m =-  mask @res do+  mask do     a <- takeBlock     a' <- onException (raise (m a)) (putBlock a)     putBlock a'@@ -154,12 +141,12 @@ -- but not the action. -- Equivalent to 'Control.Concurrent.MVar.withMVar'. use ::-  ∀ a b res r .-  Members [Sync a, Mask res, Resource] r =>+  ∀ a b r .+  Members [Sync a, Mask, Resource] r =>   (a -> Sem r b) ->   Sem r b use m =-  mask @res do+  mask do     a <- takeBlock     finally (restore (raise (m a))) (putBlock a) {-# inline use #-}@@ -167,12 +154,12 @@ -- |Run an action with the current value of the 'Sync' variable with async exceptions masked for the entire procedure. -- Equivalent to 'Control.Concurrent.MVar.withMVarMasked'. useMasked ::-  ∀ a b res r .-  Members [Sync a, Mask res, Resource] r =>+  ∀ a b r .+  Members [Sync a, Mask, Resource] r =>   (a -> Sem r b) ->   Sem r b useMasked m =-  mask @res do+  mask do     a <- takeBlock     finally (raise (m a)) (putBlock a) {-# inline useMasked #-}
polysemy-conc.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           polysemy-conc-version:        0.9.0.0+version:        0.10.0.0 synopsis:       Polysemy effects for concurrency description:    See https://hackage.haskell.org/package/polysemy-conc/docs/Polysemy-Conc.html category:       Concurrency@@ -17,6 +17,9 @@ license:        BSD-2-Clause-Patent license-file:   LICENSE build-type:     Simple+extra-source-files:+    changelog.md+    readme.md  source-repository head   type: git@@ -30,18 +33,24 @@       Polysemy.Conc.Data.QueueResult       Polysemy.Conc.Effect.Critical       Polysemy.Conc.Effect.Events+      Polysemy.Conc.Effect.Gate       Polysemy.Conc.Effect.Interrupt+      Polysemy.Conc.Effect.Lock       Polysemy.Conc.Effect.Mask       Polysemy.Conc.Effect.Monitor       Polysemy.Conc.Effect.Queue       Polysemy.Conc.Effect.Race       Polysemy.Conc.Effect.Scoped+      Polysemy.Conc.Effect.Semaphore       Polysemy.Conc.Effect.Sync       Polysemy.Conc.Effect.SyncRead       Polysemy.Conc.Events+      Polysemy.Conc.Gate       Polysemy.Conc.Interpreter.Critical       Polysemy.Conc.Interpreter.Events+      Polysemy.Conc.Interpreter.Gate       Polysemy.Conc.Interpreter.Interrupt+      Polysemy.Conc.Interpreter.Lock       Polysemy.Conc.Interpreter.Mask       Polysemy.Conc.Interpreter.Monitor       Polysemy.Conc.Interpreter.Queue.Pure@@ -49,6 +58,7 @@       Polysemy.Conc.Interpreter.Queue.TBM       Polysemy.Conc.Interpreter.Race       Polysemy.Conc.Interpreter.Scoped+      Polysemy.Conc.Interpreter.Semaphore       Polysemy.Conc.Interpreter.Stack       Polysemy.Conc.Interpreter.Sync       Polysemy.Conc.Interpreter.SyncRead@@ -58,6 +68,7 @@       Polysemy.Conc.Queue.Timeout       Polysemy.Conc.Race       Polysemy.Conc.Retry+      Polysemy.Conc.Semaphore       Polysemy.Conc.Sync       Polysemy.Conc.SyncRead   hs-source-dirs:@@ -129,7 +140,7 @@     , containers     , incipit-core >=0.3     , polysemy >=1.6-    , polysemy-resume >=0.3+    , polysemy-resume >=0.5     , polysemy-time >=0.3     , stm     , stm-chans >=2
+ readme.md view
@@ -0,0 +1,8 @@+# About++This library provides [Polysemy] effects for using STM queues, MVars, signal handling and racing.++Please visit [Hackage] for documentation.++[Polysemy]: https://hackage.haskell.org/package/polysemy+[Hackage]: https://hackage.haskell.org/package/polysemy-conc/docs/Polysemy-Conc.html
test/Main.hs view
@@ -3,6 +3,7 @@ import Hedgehog (property, test, withTests) import Polysemy.Conc.Test.EventsTest (test_events) import Polysemy.Conc.Test.InterruptTest (test_interrupt)+import Polysemy.Conc.Test.LockTest (test_lock) import Polysemy.Conc.Test.MaskTest (test_mask) import Polysemy.Conc.Test.MonitorTest (test_monitorBasic, test_monitorClockSkew) import Polysemy.Conc.Test.QueueTest (@@ -13,8 +14,8 @@   test_queueTBM,   test_queueTimeoutTBM,   )-import Polysemy.Conc.Test.ScopedTest (test_scopedResumableWith, test_scopedWith)-import Polysemy.Conc.Test.SyncTest (test_sync)+import Polysemy.Conc.Test.ScopedTest (test_scoped)+import Polysemy.Conc.Test.SyncTest (test_sync, test_syncLock) import Polysemy.Test (unitTest) import Test.Tasty (TestTree, defaultMain, testGroup) import Test.Tasty.Hedgehog (testProperty)@@ -34,8 +35,10 @@       testProperty "events" (withTests 100 (property (test test_events)))     ],     testGroup "sync" [-      unitTest "sync" test_sync+      unitTest "sync" test_sync,+      unitTest "lock" test_syncLock     ],+    test_lock,     testGroup "interrupt" [       unitTest "interrupt" test_interrupt     ],@@ -46,10 +49,7 @@       unitTest "basic" test_monitorBasic,       unitTest "clock skew" test_monitorClockSkew     ],-    testGroup "scoped" [-      unitTest "scopedWith" test_scopedWith,-      unitTest "scopedResumableWith" test_scopedResumableWith-    ]+    test_scoped   ]  main :: IO ()
test/Polysemy/Conc/Test/EventsTest.hs view
@@ -1,6 +1,5 @@ module Polysemy.Conc.Test.EventsTest where -import Control.Concurrent.Chan.Unagi.Bounded (OutChan) import Polysemy.Test (UnitTest, assertJust, runTestAuto)  import qualified Polysemy.Conc.Effect.Events as Events@@ -19,22 +18,22 @@   interpretEventsChan @Int $   interpretEventsChan @Text do     thread1 <- async do-      Events.subscribe @Int @(OutChan Int) do+      Events.subscribe @Int do         Sync.putBlock (Proxy @1)         Events.consume @Int     thread2 <- async do-      Events.subscribe @Int @(OutChan Int) do+      Events.subscribe @Int do         Sync.putBlock (Proxy @2)         Events.consume @Int     thread3 <- async do-      Events.subscribe @Text @(OutChan Text) do+      Events.subscribe @Text do         Sync.putBlock (Proxy @3)         Events.consume @Text     Sync.takeBlock @(Proxy 1)     Sync.takeBlock @(Proxy 2)     Sync.takeBlock @(Proxy 3)-    Events.publish @Text @(OutChan Text) "test"-    Events.publish @Int @(OutChan Int) 1+    Events.publish @Text "test"+    Events.publish @Int 1     num1 <- await thread1     num2 <- await thread2     text1 <- await thread3
test/Polysemy/Conc/Test/LockTest.hs view
@@ -1,26 +1,57 @@+{-# options_ghc -fplugin=Polysemy.Plugin #-}+ module Polysemy.Conc.Test.LockTest where -import Data.Time (Day, UTCTime)-import Polysemy.Test (UnitTest, assertEq, runTestAuto)-import qualified Polysemy.Time as Time-import Polysemy.Time (MicroSeconds (MicroSeconds), interpretTimeGhc)+import Polysemy.Test (UnitTest, assert, assertJust, runTestAuto, unitTest)+import Polysemy.Time (GhcTime, MilliSeconds (MilliSeconds), Seconds (Seconds), interpretTimeGhc)+import Test.Tasty (TestTree, testGroup) -import Polysemy.Conc.AtomicState (interpretAtomic)+import qualified Polysemy.Conc.Effect.Lock as Lock+import Polysemy.Conc.Effect.Lock (Lock)+import Polysemy.Conc.Effect.Mask (Mask)+import Polysemy.Conc.Effect.Race (Race)+import qualified Polysemy.Conc.Effect.Sync as Sync+import Polysemy.Conc.Interpreter.Lock (interpretLockReentrant)+import Polysemy.Conc.Interpreter.Mask (interpretMaskFinal) import Polysemy.Conc.Interpreter.Race (interpretRace)-import Polysemy.Conc.Interpreter.Sync (interpretSyncAs)-import Polysemy.Conc.Sync (lock)+import Polysemy.Conc.Interpreter.Sync (interpretSync)+import Polysemy.Conc.Race (timeout_) -test_lock :: UnitTest+interpretLockTest ::+  Members [Resource, Embed IO, Final IO] r =>+  InterpretersFor [Lock, Mask, Race, Async, GhcTime] r+interpretLockTest =+  interpretTimeGhc .+  asyncToIOFinal .+  interpretRace .+  interpretMaskFinal .+  interpretLockReentrant++test_lockBasic :: UnitTest+test_lockBasic =+  runTestAuto $ interpretLockTest $ interpretSync @(Proxy 1) $ interpretSync @(Proxy 2) do+    t1 <- async do+      Lock.lock do+        assert =<< Sync.putTry (Proxy @1)+        assertJust Proxy =<< Sync.wait @(Proxy 2) (Seconds 5)+    assertJust Proxy =<< Sync.wait @(Proxy 1) (Seconds 5)+    assert =<< Lock.lockOr (pure True) (pure False)+    assert =<< timeout_ (pure True) (MilliSeconds 50) (Lock.lock (pure False))+    assert =<< Sync.putTry (Proxy @2)+    assertJust () =<< await t1++test_lockReentry :: UnitTest+test_lockReentry =+  runTestAuto $ interpretLockTest do+    Lock.lock do+      assert =<< Lock.lockOr (pure False) (pure True)+      assertJust True =<< await =<< async do+        assert =<< timeout_ (pure True) (MilliSeconds 50) (Lock.lock (pure False))+        Lock.lockOr (pure True) (pure False)++test_lock :: TestTree test_lock =-  runTestAuto $-  interpretTimeGhc $-  asyncToIOFinal $-  interpretRace $-  interpretSyncAs () $-  interpretAtomic (0 :: Int) do-    void $ sequenceConcurrently @[] $ [(1 :: Int)..100] $> do-      lock () do-        cur <- atomicGet @Int-        Time.sleep @UTCTime @Day (MicroSeconds 100)-        atomicPut (cur + 1)-    assertEq @Int @IO 100 =<< atomicGet+  testGroup "lock" [+    unitTest "basic" test_lockBasic,+    unitTest "reentry" test_lockReentry+  ]
test/Polysemy/Conc/Test/ScopedTest.hs view
@@ -2,13 +2,19 @@  module Polysemy.Conc.Test.ScopedTest where -import Control.Concurrent.STM (TVar, atomically, newTVarIO, readTVarIO, writeTVar)+import Control.Concurrent.STM (TVar, atomically, modifyTVar', newTVarIO, readTVarIO, writeTVar) import Polysemy.Resume (Stop, stop, (!!))-import Polysemy.Test (UnitTest, runTestAuto, (===))+import Polysemy.Test (UnitTest, runTestAuto, unitTest, (===))+import Test.Tasty (TestTree, testGroup) -import Polysemy.Conc.Effect.Scoped (scoped)-import Polysemy.Conc.Interpreter.Scoped (interpretScopedResumableWithH, interpretScopedWithH)+import Polysemy.Conc.Effect.Scoped (rescope, scoped)+import Polysemy.Conc.Interpreter.Scoped (interpretScoped, interpretScopedH', interpretScopedResumableWithH, interpretScopedWithH) +newtype Par =+  Par { unPar :: Int }+  deriving stock (Eq, Show)+  deriving newtype (Num, Real, Enum, Integral, Ord)+ data E :: Effect where   E1 :: E m Int   E2 :: E m Int@@ -44,19 +50,22 @@  scope ::   Member (Embed IO) r =>+  Par ->   (TVar Int -> Sem (F : r) a) ->   Sem r a-scope use = do-  tv <- embed (newTVarIO 20)+scope (Par n) use = do+  tv <- embed (newTVarIO n)   interpretF tv (use tv)  test_scopedWith :: UnitTest test_scopedWith =-  runTestAuto $ interpretScopedWithH @'[F] scope handleE do-    i1 <- scoped e1-    i2 <- scoped e1-    i1 === 35-    i2 === 35+  runTestAuto $ interpretScopedWithH @'[F] @_ @_ @E scope handleE do+    (i1, i2) <- scoped @_ @E 20 do+      i1 <- e1+      i2 <- scoped @_ @E 23 e1+      pure (i1, i2)+    35 === i1+    38 === i2  handleRE ::   Member (Embed IO) r =>@@ -72,28 +81,94 @@   E2 ->     pureT =<< f -interpretFR ::-  Members [Stop Int, Embed IO] r =>-  TVar Int ->-  InterpreterFor F r-interpretFR tv =-  interpret \ F -> do-    embed (atomically (writeTVar tv 7))-    pure 5- scopeR ::   Member (Embed IO) r =>+  Par ->   (TVar Int -> Sem (F : Stop Int : r) a) ->   Sem (Stop Int : r) a-scopeR use = do-  tv <- embed (newTVarIO 20)+scopeR (Par n) use = do+  tv <- embed (newTVarIO n)   _ <- interpretF tv (use tv)   stop . (50 +) =<< embed (readTVarIO tv)  test_scopedResumableWith :: UnitTest test_scopedResumableWith =   runTestAuto $ interpretScopedResumableWithH @'[F] scopeR handleRE do-    i1 <- scoped e1 !! pure-    i2 <- scoped e2 !! pure-    i1 === 25-    i2 === 57+    i1 <- scoped 20 e1 !! pure+    i2 <- scoped 23 e2 !! pure+    25 === i1+    57 === i2++scopeH ::+  Member (Embed IO) r =>+  Par ->+  (TVar Int -> Tactical e m r a) ->+  Tactical e m r a+scopeH (Par n) use = do+  tv <- embed (newTVarIO n)+  use tv++handleH ::+  Member (Embed IO) r =>+  TVar Int ->+  E (Sem r0) a ->+  Tactical e (Sem r0) r a+handleH tv = \case+  E1 -> do+    embed (atomically (modifyTVar' tv (+1)))+    pureT =<< embed (readTVarIO tv)+  E2 ->+    pureT 23++test_scopedH :: UnitTest+test_scopedH =+  runTestAuto $ interpretScopedH' scopeH handleH do+    r <- scoped @_ @E 100 do+      i1 <- e1+      i2 <- scoped @_ @E 200 e1+      i3 <- e1+      pure (i1, i2, i3)+    (101, 201, 102) === r++data RPar =+  RPar {+    rpD :: Double,+    rpB :: Bool+  }+  deriving stock (Eq, Show)++data RRes =+  RRes {+    rrD :: Double,+    rrI :: Int+  }+  deriving stock (Eq, Show)++scopeR1 :: RPar -> (RRes -> Sem r a) -> Sem r a+scopeR1 (RPar d b) use =+  use (RRes (d * 2) (if b then 1 else 2))++handleR1 :: RRes -> E m x -> Sem r x+handleR1 (RRes d i) = \case+  E1 -> pure (i + floor (d * 3))+  E2 -> pure (i + floor (d * 4))++rescopeP :: Int -> RPar+rescopeP i =+  RPar (fromIntegral i) False++test_rescope :: UnitTest+test_rescope =+  runTestAuto $ interpretScoped scopeR1 handleR1 do+    r <- rescope rescopeP do+      scoped @_ @E 100 do+        e1+    602 === r+++test_scoped :: TestTree+test_scoped =+  testGroup "scoped" [+    unitTest "scopedWith" test_scopedWith,+    unitTest "scopedResumableWith" test_scopedResumableWith+  ]
test/Polysemy/Conc/Test/SyncTest.hs view
@@ -1,12 +1,17 @@ module Polysemy.Conc.Test.SyncTest where +import Data.Time (Day, UTCTime) import Polysemy.Test (UnitTest, assertEq, runTestAuto)+import qualified Polysemy.Time as Time+import Polysemy.Time (MicroSeconds (MicroSeconds), interpretTimeGhc) +import Polysemy.Conc.AtomicState (interpretAtomic) import Polysemy.Conc.Effect.Race (Race) import qualified Polysemy.Conc.Effect.Sync as Sync import Polysemy.Conc.Effect.Sync (Sync) import Polysemy.Conc.Interpreter.Race (interpretRace)-import Polysemy.Conc.Interpreter.Sync (interpretSync)+import Polysemy.Conc.Interpreter.Sync (interpretSync, interpretSyncAs)+import Polysemy.Conc.Sync (lock)  data Thread1 = Thread1 data Thread2 = Thread2@@ -51,3 +56,18 @@   runTestAuto do     result <- run $ sequenceConcurrently @[] [thread1, thread2]     assertEq @_ @IO [Just 3, Just 2] result++test_syncLock :: UnitTest+test_syncLock =+  runTestAuto $+  interpretTimeGhc $+  asyncToIOFinal $+  interpretRace $+  interpretSyncAs () $+  interpretAtomic (0 :: Int) do+    void $ sequenceConcurrently @[] $ [(1 :: Int)..100] $> do+      lock () do+        cur <- atomicGet @Int+        Time.sleep @UTCTime @Day (MicroSeconds 100)+        atomicPut (cur + 1)+    assertEq @Int @IO 100 =<< atomicGet