churros 0.1.0.3 → 0.1.1.0
raw patch · 6 files changed
+114/−28 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Control.Churro.Transport.Chan: type TransportChan a = (Chan (Maybe a), Chan (Maybe a))
- Control.Churro.Types: c2c :: Transport t => (a1 -> a2) -> t (Maybe a1) -> t (Maybe a2) -> IO ()
+ Control.Churro.Types: c2c :: Transport t => (i -> o) -> t (Maybe i) -> t (Maybe o) -> IO ()
- Control.Churro.Types: flex :: Transport t => IO (t a)
+ Control.Churro.Types: flex :: Transport t => IO (t a, t a)
Files
- CHANGELOG.md +7/−1
- README.md +70/−0
- churros.cabal +5/−3
- src/Control/Churro/Transport.hs +3/−3
- src/Control/Churro/Transport/Chan.hs +5/−2
- src/Control/Churro/Types.hs +24/−19
CHANGELOG.md view
@@ -1,4 +1,10 @@-# Revision history for churros+# Revision history for Churros++## 0.1.0.4 -- 2020-10-15++* Transport method `flex` now returns a pair of channels to move towards support for Unagi.+* Addition of new prelude methods such as `sources`.+* Adding README.md to Hackage contents page. ## 0.1.0.3 -- 2020-10-12
+ README.md view
@@ -0,0 +1,70 @@+# Churros++> Chan + Arrow = Churro++Simple alternative to Conduit, Pipes, Streams, Machines, etc.++Use-case is CSP like scenarios where you need a graph of actors.++Developed from a history of attempting to use co-routines libraries for setting up complicated asynchronous processes+such as collections of MIDI instruments, etc, but being frustrated by not easily being able to conditionally+consume and emit events. In these situations I'd fall back on creating a bunch of Chans and piping events manually.+Churros just formalises that strategy to help you get it right!++Advantages over other alternatives:++* Focus on IO processes+* Dynamic choice of consumption/production+* Arrow instance+* Choice of transport via the `Transport` class++Disadvantages:++* No pure interface!+* No expressive return type encoded in the Churro datatype (could this be addressed?)+* 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!++## Examples++See `./test/` directory for more extensive examples.++```haskell+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+```++## Testing++Cabal test-suite including doctests:++> cabal exec cabal test++Or for itterative development:++> find {src,test} | entr -- cabal exec -- doctest -isrc -itest test/Churro/Test/Examples.hs++## TODO++* [x] Recovery/Retry capability+* [x] Fix await deadlock+* [x] Generic Chan functions, then specific newtype+* [x] Stop using list functions+* [x] Different transport options, buffered, etc.+* [x] Write doctests for functionality+* [x] Get Doctests working as part of the cabal test-suite+* [ ] Bundle in/out channels in the Transport class to allow Unagi to implement it+* [ ] Create profunctor instance+* [ ] Create contravariant functor instance+* [ ] Create ArrowChoice instance+* [ ] Create ArrowLoop instance+* [x] Allow returning of results from run functions+* [x] Get haddocks rendering correctly - Including contents+* [ ] Different transports for sections of the graph+* [ ] Allow configurable parallelism+* [x] Early termination if downstream consumer completes+ - [x] Ensure that infinite lists work when partially consumed
churros.cabal view
@@ -1,20 +1,22 @@ cabal-version: 2.2 name: churros-version: 0.1.0.3+version: 0.1.1.0 license-file: LICENSE author: Lyndon Maydwell maintainer: lyndon@sordina.net homepage: http://github.com/sordina/churros bug-reports: http://github.com/sordina/churros/issues build-type: Simple-extra-source-files: CHANGELOG.md license: MIT synopsis: Channel/Arrow based streaming computation library. category: Data, Control description: The Churro library takes an opinionated approach to streaming by focusing on IO processes and allowing different transport options.-+extra-doc-files: + CHANGELOG.md+ README.md+ source-repository head type: git location: git@github.com:sordina/churros.git
src/Control/Churro/Transport.hs view
@@ -20,9 +20,9 @@ -- >>> import Control.Concurrent.Chan -- >>> :{ -- do--- c <- flex :: IO (Chan (Maybe (Maybe Int)))--- l2c c (map Just [1,2] ++ [Nothing])--- yankAll' c print+-- (i,o) <- flex :: IO (TransportChan (Maybe Int))+-- l2c i (map Just [1,2] ++ [Nothing])+-- yankAll' o print -- :} -- Just (Just 1) -- Just (Just 2)
src/Control/Churro/Transport/Chan.hs view
@@ -12,11 +12,14 @@ import Data.Void instance Transport Chan where- flex = newChan yank = readChan yeet = writeChan+ flex = do + c <- newChan+ return (c,c) -type ChurroChan = Churro Chan+type ChurroChan = Churro Chan+type TransportChan a = (Chan (Maybe a), Chan (Maybe a)) -- | Convenience function for running a Churro with a Chan Transport. --
src/Control/Churro/Types.hs view
@@ -45,13 +45,18 @@ -- * Chan (Included in `Control.Churro.Transport.Chan`) -- * TChan -- * Seq+-- * Unagi -- * Various buffered options -- -- Transports used in conjunction with Churros wrap items in Maybe so that once a source has been depleted it can signal completion with -- a Nothing item. -- +-- The flex method returns two transports, so that channels such as unagi that create an in/outs pair can have a Transport instance.+-- +-- Channels like Chan that have a single channel act as in/out simply reuse the same channel in the pair returned.+-- class Transport t where- flex :: IO (t a) -- ^ Create a new Transport+ flex :: IO (t a, t a) -- ^ Create a new pair of transports. yank :: t a -> IO a -- ^ Yank an item of the Transport yeet :: t a -> a -> IO () -- ^ Yeet an item onto the Transport @@ -68,10 +73,10 @@ instance Transport t => Functor (Churro t i) where fmap f c = Churro do (i,o,a) <- runChurro c- o' <- flex- a' <- async do+ (i',o') <- flex+ a' <- async do finally' (cancel a) do- c2c f o o'+ c2c f o i' wait a return (i,o',a') @@ -86,9 +91,9 @@ -- 1 instance Transport t => Category (Churro t) where id = Churro do- a <- async (return ())- c <- flex- return (c,c,a)+ (i,o) <- flex+ a <- async (return ())+ return (i,o,a) g . f = Churro do (fi, fo, fa) <- runChurro f@@ -164,16 +169,16 @@ arr = flip fmap id first c = Churro do- (i,o,a) <- runChurro c- i' <- flex- o' <- flex+ (i,o,a) <- runChurro c+ (ai',ao') <- flex+ (bi',bo') <- flex let go = do- is <- yank i'+ is <- yank ao' yeet i (fmap fst is) os <- yank o- yeet o' $ (,) <$> os <*> fmap snd is+ yeet bi' $ (,) <$> os <*> fmap snd is case (is, os) of (Just _, Just _) -> go@@ -181,10 +186,10 @@ a' <- async do go- yeet o' Nothing+ yeet bi' Nothing wait a - return (i',o',a')+ return (ai',bo',a') -- ** Helpers @@ -194,10 +199,10 @@ -- buildChurro :: Transport t => (t (Maybe i) -> t (Maybe o) -> IO ()) -> Churro t i o buildChurro cb = Churro do- i <- flex- o <- flex- a <- async do cb i o- return (i,o,a)+ (ai,ao) <- flex+ (bi,bo) <- flex+ a <- async do cb ao bi+ return (ai,bo,a) -- | Yeet all items from a list into a transport. -- @@ -237,7 +242,7 @@ -- -- Raw items are used so `Nothing` should be Yeeted once the transport is depleted. -- -c2c :: Transport t => (a1 -> a2) -> t (Maybe a1) -> t (Maybe a2) -> IO ()+c2c :: Transport t => (i -> o) -> t (Maybe i) -> t (Maybe o) -> IO () c2c f i o = yankAll' i (yeet o . fmap f) -- | Flipped `finally`.