packages feed

schedule 0.1.0.0 → 0.2.0.0

raw patch · 11 files changed

+94/−75 lines, 11 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Arrow.Schedule: type RunSchedA t a = forall i o. ((i, Schedule t) -> (o, Schedule t)) -> a i o
+ Control.Arrow.Schedule: type RunSched t a = forall i o. ((i, Schedule t) -> (o, Schedule t)) -> a i o
+ Data.Schedule: checkTask :: Schedule t -> Task t -> Bool
- Control.Arrow.Schedule: getInput :: Arrow a => RunSchedA t a -> a TickDelta (Either Tick i) -> a i' (Either Tick i)
+ Control.Arrow.Schedule: getInput :: Arrow a => RunSched t a -> a TickDelta (Either Tick i) -> a i' (Either Tick i)
- Control.Arrow.Schedule: mkOutput :: (ArrowChoice a, Monoid o) => RunSchedA t a -> a (Tick, t) o -> a i o -> a (Either Tick i) o
+ Control.Arrow.Schedule: mkOutput :: (ArrowChoice a, Monoid o) => RunSched t a -> a (Tick, t) o -> a i o -> a (Either Tick i) o
- Control.Arrow.Schedule: runTick :: (ArrowChoice a, Monoid o) => RunSchedA t a -> a (Tick, t) o -> a Tick o
+ Control.Arrow.Schedule: runTick :: (ArrowChoice a, Monoid o) => RunSched t a -> a (Tick, t) o -> a Tick o
- Control.Arrow.Schedule: runTicksTo :: (ArrowChoice a, Monoid o) => RunSchedA t a -> a (Tick, t) o -> a Tick o
+ Control.Arrow.Schedule: runTicksTo :: (ArrowChoice a, Monoid o) => RunSched t a -> a (Tick, t) o -> a Tick o
- Control.Arrow.Schedule: tickTask :: (ArrowChoice a, ArrowApply a, Monoid o) => RunSchedA t a -> (forall f. Applicative f => (Tick -> f (Tick, t)) -> i -> f it) -> a it o -> a i o
+ Control.Arrow.Schedule: tickTask :: (ArrowChoice a, ArrowApply a, Monoid o) => RunSched t a -> (forall f. Applicative f => (Tick -> f (Tick, t)) -> i -> f it) -> a it o -> a i o

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for schedule +## 0.2.0.0 -- 2019-12-20++* Minor API and documentation tweaks.+ ## 0.1.0.0 -- 2019-12-20  * Initial release.
schedule.cabal view
@@ -1,6 +1,6 @@ Cabal-Version:       2.4 Name:                schedule-Version:             0.1.0.0+Version:             0.2.0.0 Synopsis:            Pure deterministic scheduled computations Description:   Schedule computations to run later, in a pure and deterministic way.
src/Control/Arrow/Schedule.hs view
@@ -5,11 +5,11 @@ {-| Run scheduled computations in any (stateful) arrow, using an adapter.  This module mostly contains utilities for dealing with clock inputs. To get or-set the existing timeouts, use your 'RunSchedA' adapter on one of the functions+set the existing timeouts, use your 'RunSched' adapter on one of the functions from "Data.Schedule", which this module also re-exports. -} module Control.Arrow.Schedule-  ( RunSchedA+  ( RunSched   , runTick   , runTicksTo   , getInput@@ -44,10 +44,10 @@ -- -- This could be pure (e.g. 'Control.Arrow.Transformer.State.StateArrow') or -- impure (e.g. reference to a 'Control.Monad.Primitive.Extra.PrimST').-type RunSchedA t a = forall i o . ((i, Schedule t) -> (o, Schedule t)) -> a i o+type RunSched t a = forall i o . ((i, Schedule t) -> (o, Schedule t)) -> a i o  runTick-  :: (ArrowChoice a, Monoid o) => RunSchedA t a -> a (Tick, t) o -> a Tick o+  :: (ArrowChoice a, Monoid o) => RunSched t a -> a (Tick, t) o -> a Tick o runTick runS runTickTask = whileJustA $ proc tick -> do   r' <- runS (stA popOrTick) -< ()   case r' of@@ -59,7 +59,7 @@       returnA -< Just r  runTicksTo-  :: (ArrowChoice a, Monoid o) => RunSchedA t a -> a (Tick, t) o -> a Tick o+  :: (ArrowChoice a, Monoid o) => RunSched t a -> a (Tick, t) o -> a Tick o runTicksTo runS runTask = whileJustA $ proc tick -> do   tick' <- runS (getA tickNow) -< ()   if tick' >= tick@@ -68,7 +68,7 @@  getInput   :: (Arrow a)-  => RunSchedA t a+  => RunSched t a   -> a TickDelta (Either Tick i)   -> a i' (Either Tick i) getInput runS getTimedInput =@@ -76,23 +76,24 @@  mkOutput   :: (ArrowChoice a, Monoid o)-  => RunSchedA t a+  => RunSched t a   -> a (Tick, t) o   -> a i o   -> a (Either Tick i) o mkOutput runS runTask runInput = runTicksTo runS runTask ||| runInput --- | A more general version of 'mkOutput' that uses a prism-like optic.+-- | A more general version of 'mkOutput' that uses a+-- 'Control.Lens.Prism.Prism'-like optic. -- -- Given an inner computation @a it o@ where one branch of the @it@ type has--- a @(Tick, t)@ tuple that represents individual input tasks, return an outer--- computation of type @a i o@ where the @i@ type only has a @Tick@. When the--- outer computation receives these @Tick@ inputs, it automatically resolves--- the relevant tasks of type @t@ that are active for that @Tick@, and passes+-- a @('Tick', t)@ tuple representing individual input tasks, return an outer+-- computation of type @a i o@ where the @i@ type only has a 'Tick'. When the+-- outer computation receives these 'Tick' inputs, it automatically resolves+-- the relevant tasks of type @t@ that are active for that 'Tick', and passes -- each tuple in sequence to the wrapped inner computation. tickTask   :: (ArrowChoice a, ArrowApply a, Monoid o)-  => RunSchedA t a+  => RunSched t a   -> (forall f . Applicative f => (Tick -> f (Tick, t)) -> i -> f it)   -> a it o   -> a i o
src/Control/Clock.hs view
@@ -15,77 +15,77 @@  {-| A maybe-impure supplier of time, to a pure scheduled computation. -    The type @c@ is the computational context where clock operations occur,-    e.g. a 'Monad' such as 'IO'.+The type @c@ is the computational context where clock operations occur, e.g. a+'Monad' such as 'IO'. -    Clock implementations /must/ be monotonic. See "System.Time.Monotonic" for-    an example on how to wrap non-monotonic clocks to be monotonic.+Clock implementations /must/ be monotonic. See "System.Time.Monotonic" for an+example on how to wrap non-monotonic clocks to be monotonic. -} data Clock c = Clock {     -- | Get the current time.     clockNow   :: !(c Tick)     {-| Suspend the current computation for a given number of ticks. -        Nothing else in the computation runs until the suspension is over.-        Afterwards, 'clockNow' will give the expected value, i.e. for all @n@:+    Nothing else in the computation runs until the suspension is over.+    Afterwards, 'clockNow' will give the expected value, i.e. for all @n@: -        > do-        >     old <- clockNow-        >     clockDelay n-        >     new <- clockNow-        >     let new' = assert (old + n <= new) new+    > do+    >     old <- clockNow+    >     clockDelay n+    >     new <- clockNow+    >     let new' = assert (old + n <= new) new -        The relation is '<=' not '==', because the computer might have slept-        during the mean time or something. On the other hand, if the underlying-        physical clock might delay for a shorter period than requested, then-        implementations of this function /must/ loop-delay until the '<='-        condition is satisfied.+    The relation is '<=' not '==', because the computer might have slept during+    the mean time or something. On the other hand, if the underlying physical+    clock might delay for a shorter period than requested, then implementations+    of this function /must/ loop-delay until the '<=' condition is satisfied. -        The above is the only condition that scheduled computations should rely-        on, and any actual physical real delay is up to the implementation.-     -}+    The above is the only condition that scheduled computations should rely on,+    and any actual physical real delay is up to the implementation.+    -}   , clockDelay :: !(TickDelta -> c ())     {-| Interleave actions with ticks. -        This is typically recommended for the use-case where your action-        represents a stream of inputs, e.g. from the network or the user. It-        is meant to satisfy the same functionality as the @select@ system call-        found in common operating systems, used with a timeout parameter.+    This is typically recommended for the use-case where your action represents+    a stream of inputs, e.g. from the network or the user. It is meant to+    satisfy the same functionality as the @select@ system call found in common+    operating systems, used with a timeout parameter. -        If @action@ when executed repeatedly gives a sequence of results, then-        in the expression @clkAct <- clock `clockWith` action@, @runClocked-        clkAct@ when executed repeatedly gives the same sequence of results but-        with ticks interleaved in between them. Executing @finClocked clkAct@-        closes any resources and invalidates any future calls to @clkAct@.+    If @action@ when executed repeatedly gives a sequence of results, then in+    the expression @clkAct <- 'clockWith' clock action@, a subsequent call to+    @'runClocked' clkAct@ when executed repeatedly gives the same sequence of+    results but with ticks interleaved in between them. Executing @'finClocked'+    clkAct@ closes any resources and invalidates any future calls to @clkAct@. -        It is not necessary to call @finClocked@ if any part of @runClocked@-        (e.g. child threads) throws an exception - implementations should-        detect these situations and clean these up automatically. This frees-        the user of this function from requiring extra constraints which would-        be necessary if it's necessary to run @`finally` finClocked clkAct@ as-        cleanup.+    It is not necessary to call 'finClocked' if any part of 'runClocked' (e.g.+    child threads) throws an exception - implementations should detect these+    situations and clean these up automatically. This frees the user of this+    function from having to add extra constraints which would be the case if it+    had been necessary to run @'Control.Exception.finally' ... (finClocked+    clkAct)@ as cleanup.     -}   , clockWith  :: !(forall a. c a -> c (Clocked c a))     {-| Given an action, run it with a timeout. -        This is typically recommended for the use-case where your action-        represents the response to a single previously-sent request.+    This is typically recommended for the use-case where your action represents+    the response to a single previously-sent request. -        The action may complete despite the timeout firing, in which case its-        result will be lost. This is in general unavoidable and is a common-        property that one simply has to live with in distributed systems. If-        you run the input action repeatedly, then this property applies *for-        every execution*, i.e. it is possible that you get 10 timeouts even-        though the action succeeded 10 times, and you'll lose 10 results.+    The action may complete despite the timeout firing, in which case its+    result will be lost. This is in general unavoidable and is a common+    property that one simply has to live with in distributed systems. If you+    run the input action repeatedly, then this property applies *for every+    execution*, i.e. it is possible that you get 10 timeouts even though the+    action succeeded 10 times, and you'll lose 10 results. -        If you want all results of all actions, use @clockWith@ instead. The-        downside with that, is that it's slightly less efficient than this, as-        it will interleave every single 'Tick' event and it is up to you to-        deal with skipping/ignoring any of them.+    If you want all results of all actions, use @clockWith@ instead. The+    downside with that, is that it's slightly less efficient than this, as it+    will interleave every single 'Tick' event and it is up to you to deal with+    skipping/ignoring any of them.     -}   , clockTimer :: !(forall a. TickDelta -> c a -> c (Either Tick a)) } +-- | Run 'clockDelay' then 'clockNow'. clockTick :: Monad c => Clock c -> TickDelta -> c Tick clockTick clock d = clockDelay clock d >> clockNow clock 
src/Control/Monad/Primitive/Extra.hs view
@@ -5,7 +5,7 @@  {-| Extra utilities and abstractions for "Control.Monad.Primitive". -The API structure is stable, but the naming is not very good and may change.+The API structure is stable, but __the naming is not great and may change__. Ideally we would push this upstream into "Control.Monad.Primitive" itself. -} module Control.Monad.Primitive.Extra
src/Control/Monad/Schedule.hs view
@@ -80,13 +80,14 @@   -> (Either Tick i -> m a) mkOutput runS runTask runInput = runTicksTo runS runTask `either` runInput --- | A more general version of 'mkOutput' that uses a prism-like optic.+-- | A more general version of 'mkOutput' that uses a+-- 'Control.Lens.Prism.Prism'-like optic. -- -- Given an inner computation @it -> m a@ where one branch of the @it@ type has--- a @(Tick, t)@ tuple that represents individual input tasks, return an outer--- computation of type @i -> m a@ where the @i@ type only has a @Tick@. When--- the outer computation receives these @Tick@ inputs, it automatically--- resolves the relevant tasks of type @t@ that are active for that @Tick@, and+-- a @('Tick', t)@ tuple representing individual input tasks, return an outer+-- computation of type @i -> m a@ where the @i@ type only has a 'Tick'. When+-- the outer computation receives these 'Tick' inputs, it automatically+-- resolves the relevant tasks of type @t@ that are active for that 'Tick', and -- passes each tuple in sequence to the wrapped inner computation. tickTask   :: (Monad m, Monoid a)
src/Control/Schedule/Future.hs view
@@ -7,7 +7,7 @@  {-| Pure serialisable futures. -This API is experimental at the moment, and parts of it may change.+__This API is experimental at the moment, and parts of it may change.__ -} module Control.Schedule.Future where 
src/Data/Rsv/Common.hs view
@@ -1,6 +1,18 @@ {-# LANGUAGE DeriveGeneric              #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-| Common utilities for implementing /reservation/ data structures.++A /reservation/ data structure is one that allows multiple inserts of the same+item, by returning a unique handle for each insert operation that must be given+to the delete operation.++If you need to store the handle together with the item, e.g. so that the item+knows how to delete itself, this can be achieved via the standard Haskell+"tying the knot" technique.++__This API is experimental at the moment, and parts of it may change.__+-} module Data.Rsv.Common   ( RHandles(..)   , RHandle@@ -23,7 +35,7 @@ import           GHC.Stack              (HasCallStack)  --- Handle generator. Runtime invariants:+-- | Handle generator. Runtime invariants: -- -- 1. A handle from one generator is not used in a context that expects a -- handle from a different generator. TODO: use a string or other data to
src/Data/Rsv/RMMap.hs view
@@ -9,9 +9,9 @@  A /reservation/ data structure is one that allows multiple inserts of the same item, by returning a unique handle for each insert operation that must be given-to the deletion operation. If you need to store the handle together with the-item, e.g. so that the item knows how to delete itself, you can achieve this by-the standard Haskell "tying the knot" technique.+to the delete operation.++__This API is experimental at the moment, and parts of it may change.__ -} module Data.Rsv.RMMap   ( RMMap(..)@@ -75,9 +75,9 @@ -- which in general cannot check the complex invariants maintained by the API -- functions. Also, for all handles you obtain via a similarly non-standard -- method, including by deserialisation of a parent data structure, you must--- run @checkHandle map handle@.+-- run @'checkHandle' map handle@. ----- @Nothing@ means the check passed, else @Just errmsg@ gives a failure reason.+-- 'Nothing' means the check passed; @'Just' errmsg@ gives a failure reason. -- -- Note: this does not guard against all malicious behaviour, but it does guard -- against violation (either malicious or accidental) of the runtime invariants
src/Data/Schedule.hs view
@@ -14,6 +14,7 @@   , Schedule   , newSchedule   , checkValidity+  , checkTask   , tickNow   , tickPrev   , ticksToIdle
src/Data/Schedule/Internal.hs view
@@ -58,9 +58,9 @@ -- which in general cannot check the complex invariants maintained by the API -- functions. Also, for all 'Task's you obtain via a similarly non-standard -- method, including by deserialisation of a parent data structure, you must--- run @checkHandle schedule task@.+-- run @'checkTask' schedule task@. ----- @Nothing@ means the check passed, else @Just errmsg@ gives a failure reason.+-- 'Nothing' means the check passed; @'Just' errmsg@ gives a failure reason. -- -- Note: this does not guard against all malicious behaviour, but it does guard -- against violation (either malicious or accidental) of the runtime invariants