churros 0.1.3.0 → 0.1.4.0
raw patch · 6 files changed
+82/−27 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Control.Churro.Types: data Churro a t i o
- Control.Churro.Types: instance Control.Churro.Types.Transport t => Control.Arrow.Arrow (Control.Churro.Types.Churro () t)
- Control.Churro.Types: instance Control.Churro.Types.Transport t => GHC.Base.Applicative (Control.Churro.Types.Churro () t Data.Void.Void)
+ Control.Churro.Prelude: runWaitList_ :: Transport t => Churro () t Void b -> IO [b]
+ Control.Churro.Prelude: runWait_ :: Transport t => Churro () t Void Void -> IO ()
+ Control.Churro.Prelude: run_ :: Transport t => Churro () t Void Void -> IO (Async ())
+ Control.Churro.Prelude: sinkIO_ :: Transport t => (o -> IO ()) -> Churro () t o Void
+ Control.Churro.Prelude: sourceIO_ :: Transport t => ((o -> IO ()) -> IO ()) -> Churro () t Void o
+ Control.Churro.Types: instance (Control.Churro.Types.Transport t, GHC.Base.Monoid a) => Control.Arrow.Arrow (Control.Churro.Types.Churro a t)
+ Control.Churro.Types: instance (Control.Churro.Types.Transport t, GHC.Base.Monoid a) => GHC.Base.Applicative (Control.Churro.Types.Churro a t Data.Void.Void)
+ Control.Churro.Types: newtype Churro a t i o
- Control.Churro.Prelude: sources :: (Transport t, Monoid a) => [Source a t o] -> Source () t o
+ Control.Churro.Prelude: sources :: (Transport t, Foldable f, Traversable f) => f (Churro a t Void i) -> Churro () t Void i
Files
- CHANGELOG.md +6/−0
- README.md +3/−3
- churros.cabal +1/−1
- src/Control/Churro/Prelude.hs +49/−15
- src/Control/Churro/Types.hs +13/−8
- test/Churro/Test/Examples.hs +10/−0
CHANGELOG.md view
@@ -1,5 +1,11 @@ # Revision history for Churros +## 0.1.4.0 -- 2020-10-18++* Generalising list type to Foldable/Traversible where possible (`sources`).+* Additional documentation+* Underscore variants of prelude function that specialise Async action to `()`.+ ## 0.1.3.0 -- 2020-10-17 * Generalised functions to have Monoid for Async action result.
README.md view
@@ -40,7 +40,7 @@ * Type for the async action restricted to Monoid for most operations. * Limited ability to perform lock-step computation (although this is by design) -See [Hackage](https://hackage.haskell.org/package/churros-0.1.0.0/candidate) for more info!+See [Hackage](https://hackage.haskell.org/package/churros) for more info! ## Examples @@ -50,8 +50,8 @@ import Control.Churro main = do- runWaitChan $ sourceList [1..10] >>> processDebug "after source" >>> delay 1 {- seconds -} >>> arr succ >>> sinkPrint- wait =<< run @Chan $ sourceIO (\cb -> cb 1 >> print "Doing whatever!" >> cb 5) >>> filterC (> 3) >>> sinkIO print+ runWaitChan $ sourceList [1..10] >>> processDebug "after source" >>> delay 1 {- seconds -} >>> arr succ >>> sinkPrint+ (wait =<<) $ run @Chan $ sourceIO (\cb -> cb 1 >> print "Doing whatever!" >> cb 5) >>> filterC (> 3) >>> sinkIO print ``` ## Testing
churros.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: churros-version: 0.1.3.0+version: 0.1.4.0 license-file: LICENSE author: Lyndon Maydwell maintainer: lyndon@sordina.net
src/Control/Churro/Prelude.hs view
@@ -5,6 +5,13 @@ -- | Common transport-agnostic functions for using Churro. -- +-- Variants with a trailing underscore - E.g. `runWait_` specialised the Async action to+-- be () if you don't care about accumulating results and only processing items as they+-- pass through the pipeline.+-- +-- Variants with a trailing prime - E.g. `processRetry'`. also change the generality of the+-- types involved in some way.+-- module Control.Churro.Prelude where import Control.Churro.Types@@ -14,10 +21,10 @@ import Control.Arrow (arr) import Control.Category (id, (.), (>>>)) import Control.Concurrent (threadDelay)-import Control.Concurrent.Async (waitAny, Async, wait)+import Control.Concurrent.Async (cancel, Async, wait) import Control.Exception (Exception, SomeException, try) import Control.Monad (replicateM_, when)-import Data.Foldable (for_)+import Data.Foldable (toList, for_) import Data.Maybe (isJust) import Data.Time (NominalDiffTime) import Data.Void (Void)@@ -40,6 +47,11 @@ runWait :: Transport t => Churro a t Void Void -> IO a runWait x = wait =<< run x +-- | Version of `runWait` specialised to `()`.+-- +runWait_ :: Transport t => Churro () t Void Void -> IO ()+runWait_ = runWait+ -- | Read the output of a Churro into a list. -- -- Warning: This will block until the Churro terminates,@@ -53,11 +65,21 @@ runWaitList :: (Transport t, Monoid a) => Churro a t Void b -> IO [b] runWaitList c = runWait $ (c >>> arr' (:[])) >>>> sink +-- | Version of `runWaitList` specialised to `()`.+-- +runWaitList_ :: Transport t => Churro () t Void b -> IO [b]+runWaitList_ = runWaitList+ -- | Run a sourced and sinked (double-dipped) churro and return an async action representing the in-flight processes. -- run :: Transport t => Churro a t Void Void -> IO (Async a) run = run' +-- | Version of `run` with async return type specialised to `()`.+--+run_ :: Transport t => Churro () t Void Void -> IO (Async ())+run_ = run'+ -- | Run any churro, there is no check that this was spawned with a source, or terminated with a sink. -- This is unsafe, since the pipeline may not generate or consume in a predictable way. -- Use `run` instead unless you are confident you know what you're doing.@@ -103,6 +125,11 @@ yeet o Nothing return r +-- | Variant of `sourceIO` with Async action specialised to `()`.+-- +sourceIO_ :: Transport t => ((o -> IO ()) -> IO ()) -> Churro () t Void o+sourceIO_ = sourceIO+ -- | Combine a list of sources into a single source. -- -- Sends individual items downstream without attempting to combine them.@@ -114,18 +141,29 @@ -- >>> runWaitChan $ sources_ [pure 1, pure 1] >>> sinkPrint -- 1 -- 1-sources :: (Transport t, Monoid a) => [Source a t o] -> Source () t o+sources :: (Transport t, Foldable f, Traversable f) => f (Churro a t Void i) -> Churro () t Void i sources ss = sourceIO \cb -> do asyncs <- mapM (\s -> run $ s >>>> sinkIO cb) ss- (_, r) <- waitAny asyncs- return r+ let as = toList asyncs+ finally' (mapM_ cancel as) do+ mapM_ wait as --- | This is `sources` specialised to `()`.+-- | Variant of `sources` with Async action of sources in argument specialised to `()`.+-- sources_ :: Transport t => [Source () t o] -> Source () t o sources_ = sources -- ** Sinks +-- | Consume all items and combines them into a result via their monoid.+-- +-- >>> :set -XFlexibleContexts+-- >>> r <- runWaitChan $ pure' [1 :: Int] >>> sink+-- >>> print r+-- [1]+sink :: (Transport t, Monoid a) => Churro a t a Void+sink = sinkIO return+ -- | Consume all items with no additional effects. -- -- TODO: Decide if we should use some kind of `nf` evaluation here to force items.@@ -136,15 +174,6 @@ sink_ :: Transport t => Churro () t i Void sink_ = sinkIO (const (return ())) --- | Consume all items and combines them into a result via their monoid.--- --- >>> :set -XFlexibleContexts--- >>> r <- runWaitChan $ pure' [1 :: Int] >>> sink--- >>> print r--- [1]-sink :: (Transport t, Monoid a) => Churro a t a Void-sink = sinkIO return- -- | Consume a churro with an IO process. -- -- >>> runWaitChan $ pure 1 >>> sinkIO (\x -> print "hello" >> print (succ x))@@ -152,6 +181,11 @@ -- 2 sinkIO :: (Transport t, Monoid a) => (o -> IO a) -> Churro a t o Void sinkIO cb = buildChurro \i _o -> yankAll i cb++-- | Variant of `sinkIO` with Async action specialised to `()`.+-- +sinkIO_ :: Transport t => (o -> IO ()) -> Churro () t o Void+sinkIO_ cb = buildChurro \i _o -> yankAll i cb -- | Create a "sink" with more flexibility about when items are demanded using a higher-order "HO" callback. --
src/Control/Churro/Types.hs view
@@ -40,10 +40,10 @@ -- Convenience types of `Source`, `Sink`, and `DoubleDipped` are also defined, -- although use is not required. -- -data Churro a t i o = Churro { runChurro :: IO (In t (Maybe i), Out t (Maybe o), Async a) }-type Source a t o = Churro a t Void o-type Sink a t i = Churro a t i Void-type DoubleDipped a t = Churro a t Void Void+newtype Churro a t i o = Churro { runChurro :: IO (In t (Maybe i), Out t (Maybe o), Async a) }+type Source a t o = Churro a t Void o+type Sink a t i = Churro a t i Void+type DoubleDipped a t = Churro a t Void Void -- | The transport method is abstracted via the Transport class -- @@ -128,9 +128,9 @@ -- -- The `pure` method allows for the creation of a Churro yielding a single item. -- --- TODO: Generalise () to a Monoid constraint.+-- TODO: Write test to check Monoid return type. -- -instance Transport t => Applicative (Churro () t Void) where+instance (Transport t, Monoid a) => Applicative (Churro a t Void) where pure = pure' f <*> g = buildChurro \_i o -> do@@ -188,7 +188,10 @@ -- -- >>> runWaitChan $ pure 1 >>> (arr show &&& arr succ) >>> sinkPrint -- ("1",2)-instance Transport t => Arrow (Churro () t) where+-- +-- TODO: Write tests to check if the monoid return type is implemented correctly.+-- +instance (Transport t, Monoid a) => Arrow (Churro a t) where arr = arr' first c = Churro do@@ -240,7 +243,9 @@ a <- async do cb ai ao bi return (ai,bo,a) --- | Yeet all items from a list into a transport.+-- | Yeet all items from a list into a raw transport.+-- +-- WARNING: If you are using this to build a churro by hand make sure you yeet Nothing once you're finished. -- yeetList :: (Foldable f, Transport t) => In t a -> f a -> IO () yeetList t = mapM_ (yeet t)
test/Churro/Test/Examples.hs view
@@ -15,6 +15,8 @@ import Prelude hiding (id, (.)) import Control.Churro+import Control.Concurrent.Async (wait)+import Control.Concurrent (Chan) -- $setup -- @@ -23,6 +25,14 @@ -- >>> import Control.Concurrent (threadDelay) -- ** Tests++-- | Example from readme:+-- +-- No need to run it, just typecheck it.+readme :: IO ()+readme = do+ runWaitChan $ sourceList [1::Int ..10] >>> processDebug "after source" >>> delay 1 {- seconds -} >>> arr succ >>> sinkPrint+ (wait =<<) $ run @Chan $ sourceIO (\cb -> cb (1::Int) >> print "Doing whatever!" >> cb 5) >>> filterC (> 3) >>> sinkIO print -- | Checks that the IO nature of the churros doesn't duplicate operations. -- Actions within a pipeline should only occur once no matter how the