conduit-algorithms 0.0.4.0 → 0.0.5.0
raw patch · 5 files changed
+66/−10 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Conduit.Algorithms.Utils: enumerateC :: Monad m => Conduit a m (Int, a)
Files
- ChangeLog +4/−0
- Data/Conduit/Algorithms.hs +29/−9
- Data/Conduit/Algorithms/Tests.hs +23/−0
- Data/Conduit/Algorithms/Utils.hs +9/−0
- conduit-algorithms.cabal +1/−1
ChangeLog view
@@ -1,3 +1,7 @@+Version 0.0.5.0 2017-10-03 by luispedro+ * Add enumerateC conduit+ * Better mergeC conduit (list case)+ Version 0.0.4.0 2017-09-12 by luispedro * Fix bug in merge* conduits
Data/Conduit/Algorithms.hs view
@@ -20,6 +20,7 @@ import qualified Data.Conduit as C import qualified Data.Conduit.Internal as CI import qualified Data.Set as S+import Data.List (foldl') import Control.Monad.Trans.Class (lift) import Data.Conduit.Algorithms.Utils (awaitJust)@@ -77,22 +78,42 @@ -- -- See 'mergeC2' mergeC :: (Ord a, Monad m) => [C.Source m a] -> C.Source m a-mergeC [] = return ()-mergeC [s] = s+mergeC [a] = a mergeC [a,b] = mergeC2 a b-mergeC args = mergeC2 (mergeC right) (mergeC left)- where- right = take n args- left = drop n args- n = (length args) `div` 2+mergeC cs = CI.ConduitM $ \rest -> let+ --go :: [CI.Pipe () i o () m ()] -> CI.Pipe () i o () m ()+ go [] = rest ()+ go st = do+ st' <- mapM norm1 st+ case gettop st' of+ Nothing -> rest ()+ Just (CI.HaveOutput c_next _ v, fs, next) ->+ CI.HaveOutput (go (c_next:next)) (sequence_ fs) v+ _ -> error "This should be impossible (mergeC/go/case-gettop)"+ norm1 :: Monad m => CI.Pipe () i o () m () -> CI.Pipe () i o () m (CI.Pipe () i o () m ())+ norm1 c@CI.HaveOutput{} = return c+ norm1 c@CI.Done{} = return c+ norm1 (CI.PipeM p) = lift p >>= norm1+ norm1 (CI.NeedInput _ next) = norm1 (next ())+ norm1 (CI.Leftover next ()) = norm1 next+ gettop = foldl' collect Nothing+ collect cur CI.Done{} = cur+ collect Nothing c@(CI.HaveOutput _ f _) = Just (c, [f], [])+ collect (Just (best_c@(CI.HaveOutput _ _ best_v), fs, next)) c@(CI.HaveOutput _ f v)+ | v >= best_v = Just (best_c, f:fs, c:next)+ | otherwise = Just (c, f:fs, best_c:next)+ collect _ _ = error "This situation should be impossible (mergeC/collect)" + in go (map (($ CI.Done) . CI.unConduitM) cs)++ -- | Take two sorted sources and merge them. -- -- See 'mergeC' mergeC2 :: (Ord a, Monad m) => C.Source m a -> C.Source m a -> C.Source m a mergeC2 (CI.ConduitM s1) (CI.ConduitM s2) = CI.ConduitM $ \rest -> let go right@(CI.HaveOutput s1' f1 v1) left@(CI.HaveOutput s2' f2 v2)- | compare v1 v2 /= GT = CI.HaveOutput (go s1' left) (f1 >> f2) v1+ | v1 <= v2 = CI.HaveOutput (go s1' left) (f1 >> f2) v1 | otherwise = CI.HaveOutput (go right s2') (f1 >> f2) v2 go right@CI.Done{} (CI.HaveOutput s f v) = CI.HaveOutput (go right s) f v go (CI.HaveOutput s f v) left@CI.Done{} = CI.HaveOutput (go s left) f v@@ -108,4 +129,3 @@ go (CI.Leftover next ()) left = go next left go right (CI.Leftover next ()) = go right next in go (s1 CI.Done) (s2 CI.Done)-
Data/Conduit/Algorithms/Tests.hs view
@@ -17,6 +17,7 @@ import Data.Conduit ((.|)) import Data.List (sort) import System.Directory (removeFile)+import Control.Monad (forM_) import qualified Data.Conduit.Algorithms as CAlg import qualified Data.Conduit.Algorithms.Utils as CAlg@@ -45,13 +46,32 @@ [ CC.yieldMany i1 , CC.yieldMany i2 , CC.yieldMany i3+ , CC.yieldMany i3 ] where+ expected = sort (concat [i1, i2, i3, i3])+ i1 = [ 1, 2, 4 :: Int]+ i2 = [ 1, 4, 4, 5]+ i3 = [-1, 0, 7]++case_mergeCmonad = shouldProduce expected $+ CAlg.mergeC+ [ mYield i1+ , mYield i2+ , mYield i3+ ]+ where expected = sort (concat [i1, i2, i3])+ mYield lst = do+ let lst' = map return lst+ forM_ lst' $ \elem -> do+ elem' <- elem+ C.yield elem' i1 = [ 0, 2, 4 :: Int] i2 = [ 1, 3, 4, 5] i3 = [-1, 0, 7] + case_mergeC2 = shouldProduce [0, 1, 1, 2, 3, 5 :: Int] $ CAlg.mergeC2 (CC.yieldMany [0, 1, 2])@@ -71,6 +91,9 @@ case_groupC = shouldProduce [[0,1,2], [3,4,5], [6,7,8], [9, 10 :: Int]] $ CC.yieldMany [0..10] .| CAlg.groupC 3++case_enumerateC = shouldProduce [(0,'z'), (1,'o'), (2,'t')] $+ CC.yieldMany ("zot" :: [Char]) .| CAlg.enumerateC case_removeRepeatsC = shouldProduce [0,1,2,3,4,5,6,7,8,9, 10 :: Int] $ CC.yieldMany [0,0,0,1,1,1,2,2,3,4,5,6,6,6,6,7,7,8,9,10,10] .| CAlg.removeRepeatsC
Data/Conduit/Algorithms/Utils.hs view
@@ -8,6 +8,7 @@ -} module Data.Conduit.Algorithms.Utils ( awaitJust+ , enumerateC , groupC ) where @@ -29,6 +30,14 @@ -- http://neilmitchell.blogspot.de/2015/07/thoughts-on-conduits.html awaitJust :: Monad m => (a -> C.Conduit a m b) -> C.Conduit a m b awaitJust f = C.await >>= maybe (return ()) f++-- Conduit analogue to Python's enumerate function+enumerateC :: Monad m => C.Conduit a m (Int, a)+enumerateC = enumerateC' 0+ where+ enumerateC' !i = awaitJust $ \v -> do+ C.yield (i, v)+ enumerateC' (i + 1) -- | groupC yields the input as groups of 'n' elements. If the input is not a -- multiple of 'n', the last element will be incomplete
conduit-algorithms.cabal view
@@ -1,5 +1,5 @@ name: conduit-algorithms-version: 0.0.4.0+version: 0.0.5.0 synopsis: Conduit-based algorithms description: Algorithms on Conduits, including higher level asynchronous processing and some other utilities.