packages feed

foldl 1.2.1 → 1.2.2

raw patch · 7 files changed

+504/−73 lines, 7 filesdep +criteriondep +foldldep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: criterion, foldl

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Control.Foldl: foldOver :: Handler s a -> Fold a b -> s -> b
+ Control.Foldl: foldOverM :: Monad m => HandlerM m s a -> FoldM m a b -> s -> m b
+ Control.Foldl: mean :: Fractional a => Fold a a
+ Control.Foldl: std :: Floating a => Fold a a
+ Control.Foldl: variance :: Fractional a => Fold a a
+ Control.Foldl.ByteString: foldM :: Monad m => FoldM m ByteString a -> ByteString -> m a
+ Control.Foldl.Text: foldM :: Monad m => FoldM m Text a -> Text -> m a
- Control.Foldl: handlesM :: Monad m => HandlerM m a b -> FoldM m b r -> FoldM m a r
+ Control.Foldl: handlesM :: HandlerM m a b -> FoldM m b r -> FoldM m a r
- Control.Foldl: hoists :: Monad m => (forall x. m x -> n x) -> FoldM m a b -> FoldM n a b
+ Control.Foldl: hoists :: (forall x. m x -> n x) -> FoldM m a b -> FoldM n a b
- Control.Foldl: impurely :: Monad m => (forall x. (x -> a -> m x) -> m x -> (x -> m b) -> r) -> FoldM m a b -> r
+ Control.Foldl: impurely :: (forall x. (x -> a -> m x) -> m x -> (x -> m b) -> r) -> FoldM m a b -> r

Files

+ CHANGELOG.md view
@@ -0,0 +1,103 @@+1.2.2++* Add numerically stable `mean`, `variance`, and `std` folds+* Add `Control.Foldl.{Text,ByteString}.foldM`+* Add `foldOver`/`foldOverM`++1.2.1++* Performance improvements+* Re-export `filtered`++1.2.0++* Breaking change: Fix `handles` to fold things in the correct order (was+  previously folding things backwards and also leaking space as a result).  No+  change to behavior of `handlesM`, which was folding things in the right order+* Breaking change: Change the `Monoid` used by `Handler`/`HandlerM`+* Add `folded`++1.1.6++* Add `maximumBy` and `minimumBy`++1.1.5++* Increase lower bound on `base` from `< 4` to `< 4.5`++1.1.4++* Increase upper bound on `comonad` from `< 5` to `< 6`++1.1.3++* Increase upper bound on `profunctors` from `< 5.2` to `< 5.3`+* Add `mapM_`, `hoists`, `purely`, and `impurely`++1.1.2++* Add `lastN`, `randomN`, `sink`, and `duplicateM`+* Add `Comonad` instance for `Fold`+* Add `Profunctor` instance for `FoldM`++1.1.1++* Increase upper bound on `vector` from `< 0.11` to `< 0.12`++1.1.0++* Breaking change: Rename `pretraverse`/`pretraverseM` to `handles`/`handlesM`+* Add `Handler`+* Export `EndoM`++1.0.11++* Add `Profunctor` instance for `Fold`++1.0.10++* Add `random` and `_Fold1`++1.0.9++* Increase upper bound on `primitive` from `< 0.6` to `< 0.7`++1.0.8++* Add `revList`++1.0.7++* Add `Num` and `Fractional` instances for `Fold`/`FoldM`+* Add `count` fold for `Text` and `ByteString`++1.0.6++* Add `pretraverse` and `pretraverseM`++1.0.5++* Add `lastDef`++1.0.4++* Increase upper bounds on `transformers` from `< 0.4` to `< 0.6`+* Add `nub`, `eqNub`, and `set`++1.0.3++* Add `scan`, `generalize`, `simplify`, and `premapM`++1.0.2++* Add `list` and `vector` folds+* Add `fold` function for `Text` and `ByteString`++1.0.1++* Add support for `ByteString` and `Text` folds+* Add `Monoid` instance for `Fold`/`FoldM`++1.0.0++* Initial release
+ README.md view
@@ -0,0 +1,173 @@+# `foldl` v1.2.2++Use this `foldl` library when you want to compute multiple folds over a+collection in one pass over the data without space leaks.++For example, suppose that you want to simultaneously compute the sum of the list+and the length of the list.  Many Haskell beginners might write something like+this:++```haskell+sumAndLength :: Num a => [a] -> (a, Int)+sumAndLength xs = (sum xs, length xs)++```++However, this solution will leak space because it goes over the list in two+passes.  If you demand the result of `sum` the Haskell runtime will materialize+the entire list.  However, the runtime cannot garbage collect the list because+the list is still required for the call to `length`.++Usually people work around this by hand-writing a strict left fold that looks+something like this:++```haskell+{-# LANGUAGE BangPatterns #-}++import Data.List (foldl')++sumAndLength :: Num a => [a] -> (a, Int)+sumAndLength xs = foldl' step (0, 0) xs+  where+    step (x, y) n = (x + n, y + 1)+```++That now goes over the list in one pass, but will still leak space because the+tuple is not strict in both fields!  You have to define a strict `Pair` type to+fix this:++```haskell+{-# LANGUAGE BangPatterns #-}++import Data.List (foldl')++data Pair a b = Pair !a !b++sumAndLength :: Num a => [a] -> (a, Int)+sumAndLength xs = done (foldl' step (Pair 0 0) xs)+  where+    step (Pair x y) n = Pair (x + n) (y + 1)++    done (Pair x y) = (x, y)+```+++However, this is not satisfactory because you have to reimplement the guts of+every fold that you care about and also define a custom strict data type for+your fold.  Hand-writing the step function, accumulator, and strict data type+for every fold that you want to use gets tedious fast.  For example,+implementing something like reservoir sampling over and over is very error+prone.++What if you just stored the step function and accumulator for each individual+fold and let some high-level library do the combining for you?  That's exactly+what this library does!  Using this library you can instead write:++```haskell+import qualified Control.Foldl as Fold++sumAndLength :: Num a => [a] -> (a, Int)+sumAndLength xs = Fold.fold ((,) <$> Fold.sum <*> Fold.length) xs++-- or, more concisely:+sumAndLength = Fold.fold ((,) <$> Fold.sum <*> Fold.length)+```++To see how this works, the `Fold.sum` value is just a datatype storing the step+function and the starting state (and a final extraction function):++```haskell+sum :: Num a => Fold a a+sum = Fold (+) 0 id+```++Same thing for the `Fold.length` value:++```haskell+length :: Fold a Int+length = Fold (\n _ -> n + 1) 0 id+```++... and the `Applicative` operators combine them into a new datatype storing+the composite step function and starting state:++```haskell+(,) <$> Fold.sum <*> Fold.length = Fold step (Pair 0 0) done+  where+    step (Pair x y) = Pair (x + n) (y + 1)++    done (Pair x y) = (x, y)+```++... and then `fold` just transforms that to a strict left fold:++```haskell+fold (Fold step begin done) = done (foldl' step begin)+```++Since we preserve the step function and accumulator, we can use the `Fold` type to+fold things other than pure collections.  For example, we can fold a `Producer`+from `pipes` using the same `Fold`:++```haskell+Fold.purely Pipes.Prelude.fold ((,) <$> sum <*> length)+    :: (Monad m, Num a) => Producer a m () -> m (a, Int)+```++To learn more about this library, read the documentation in+[the main `Control.Foldl` module](http://hackage.haskell.org/package/foldl/docs/Control-Foldl.html).++## Quick start++Install [the `stack` tool](http://haskellstack.org/) and then run:++```bash+$ stack setup+$ stack ghci foldl+Prelude> import qualified Control.Foldl as Fold+Prelude Fold> Fold.fold ((,) <$> Fold.sum <*> Fold.length) [1..1000000]+(500000500000,1000000)+```++## How to contribute++Contribute a pull request if you have a `Fold` that you believe other people+would find useful.++## Development Status++[![Build Status](https://travis-ci.org/Gabriel439/Haskell-Foldl-Library.png)](https://travis-ci.org/Gabriel439/Haskell-Foldl-Library)++The `foldl` library is pretty stable at this point.  I don't expect there to be+breaking changes to the API from this point forward unless people discover new+bugs.++## License (BSD 3-clause)++Copyright (c) 2016 Gabriel Gonzalez+All rights reserved.++Redistribution and use in source and binary forms, with or without modification,+are permitted provided that the following conditions are met:++* Redistributions of source code must retain the above copyright notice, this+  list of conditions and the following disclaimer.++* Redistributions in binary form must reproduce the above copyright notice, this+  list of conditions and the following disclaimer in the documentation and/or+  other materials provided with the distribution.++* Neither the name of Gabriel Gonzalez nor the names of other contributors may+  be used to endorse or promote products derived from this software without+  specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ bench/benchmarks.hs view
@@ -0,0 +1,40 @@+module Main (main) where++import Control.Foldl+import Criterion.Main+import qualified Data.List+import Prelude hiding (length, sum)+import qualified Prelude++main :: IO ()+main = defaultMain+  [ env (return [1..10000 :: Int]) $ \ns ->+      bgroup "[1..10000 :: Int]"+        [ bgroup "sum" $ map ($ ns)+            [ bench "fold sum" .+                whnf (fold sum)+            , bench "foldM (generalize sum)" .+                whnfIO . foldM (generalize sum)+            , bench "Prelude.sum" .+                whnf Prelude.sum+            , bench "Data.List.foldl' (+) 0" .+                whnf (Data.List.foldl' (+) 0)+            ]+        , bgroup "filtered" $ map ($ ns)+            [ bench "fold (handles (filtered even) list)" .+                nf (fold (handles (filtered even) list))+            , bench "foldM (handlesM (filtered even) (generalize list))" .+                nfIO . foldM (handlesM (filtered even) (generalize list))+            , bench "filter even" .+                nf (filter even)+            ]+        , bgroup "length" $ map ($ ns)+            [ bench "fold length" .+                whnf (fold length)+            , bench "foldM (generalize length)" .+                whnfIO . foldM (generalize length)+            , bench "Prelude.length" .+                whnf Prelude.length+            ]+        ]+  ]
foldl.cabal view
@@ -1,5 +1,5 @@ Name: foldl-Version: 1.2.1+Version: 1.2.2 Cabal-Version: >=1.8.0.2 Build-Type: Simple License: BSD3@@ -15,6 +15,9 @@   folds.  Derived folds still traverse the container just once and are often as   efficient as hand-written folds. Category: Control+Extra-Source-Files:+    CHANGELOG.md+    README.md Source-Repository head     Type: git     Location: https://github.com/Gabriel439/Haskell-Foldl-Library@@ -40,3 +43,13 @@     Other-Modules:         Control.Foldl.Internal     GHC-Options: -O2 -Wall++Benchmark benchmarks+    Type: exitcode-stdio-1.0+    HS-Source-Dirs: bench+    Main-Is: benchmarks.hs+    Build-Depends:+        base,+        criterion,+        foldl+    GHC-Options: -O2 -Wall -rtsopts
src/Control/Foldl.hs view
@@ -31,6 +31,8 @@ >>> L.fold ((,) <$> L.minimum <*> L.maximum) [1..10000000] (Just 1,Just 10000000) +    You might want to try enabling the @-flate-dmd-anal@ flag when compiling+    executables that use this library to further improve performance. -}  {-# LANGUAGE ExistentialQuantification #-}@@ -63,6 +65,9 @@     , any     , sum     , product+    , mean+    , variance+    , std     , maximum     , maximumBy     , minimum@@ -105,9 +110,11 @@     , premapM     , Handler     , handles+    , foldOver     , EndoM(..)     , HandlerM     , handlesM+    , foldOverM     , folded     , filtered @@ -181,10 +188,10 @@  instance Comonad (Fold a) where     extract (Fold _ begin done) = done begin-    {-#  INLINABLE extract #-}+    {-#  INLINE extract #-}      duplicate (Fold step begin done) = Fold step begin (\x -> Fold step x done)-    {-#  INLINABLE duplicate #-}+    {-#  INLINE duplicate #-}  instance Applicative (Fold a) where     pure b    = Fold (\() _ -> ()) () (\() -> b)@@ -199,97 +206,97 @@  instance Monoid b => Monoid (Fold a b) where     mempty = pure mempty-    {-# INLINABLE mempty #-}+    {-# INLINE mempty #-}      mappend = liftA2 mappend-    {-# INLINABLE mappend #-}+    {-# INLINE mappend #-}  instance Num b => Num (Fold a b) where     fromInteger = pure . fromInteger-    {-# INLINABLE fromInteger #-}+    {-# INLINE fromInteger #-}      negate = fmap negate-    {-# INLINABLE negate #-}+    {-# INLINE negate #-}      abs = fmap abs-    {-# INLINABLE abs #-}+    {-# INLINE abs #-}      signum = fmap signum-    {-# INLINABLE signum #-}+    {-# INLINE signum #-}      (+) = liftA2 (+)-    {-# INLINABLE (+) #-}+    {-# INLINE (+) #-}      (*) = liftA2 (*)-    {-# INLINABLE (*) #-}+    {-# INLINE (*) #-}      (-) = liftA2 (-)-    {-# INLINABLE (-) #-}+    {-# INLINE (-) #-}  instance Fractional b => Fractional (Fold a b) where     fromRational = pure . fromRational-    {-# INLINABLE fromRational #-}+    {-# INLINE fromRational #-}      recip = fmap recip-    {-# INLINABLE recip #-}+    {-# INLINE recip #-}      (/) = liftA2 (/)-    {-# INLINABLE (/) #-}+    {-# INLINE (/) #-}  instance Floating b => Floating (Fold a b) where     pi = pure pi-    {-# INLINABLE pi #-}+    {-# INLINE pi #-}      exp = fmap exp-    {-# INLINABLE exp #-}+    {-# INLINE exp #-}      sqrt = fmap sqrt-    {-# INLINABLE sqrt #-}+    {-# INLINE sqrt #-}      log = fmap log-    {-# INLINABLE log #-}+    {-# INLINE log #-}      sin = fmap sin-    {-# INLINABLE sin #-}+    {-# INLINE sin #-}      tan = fmap tan-    {-# INLINABLE tan #-}+    {-# INLINE tan #-}      cos = fmap cos-    {-# INLINABLE cos #-}+    {-# INLINE cos #-}      asin = fmap sin-    {-# INLINABLE asin #-}+    {-# INLINE asin #-}      atan = fmap atan-    {-# INLINABLE atan #-}+    {-# INLINE atan #-}      acos = fmap acos-    {-# INLINABLE acos #-}+    {-# INLINE acos #-}      sinh = fmap sinh-    {-# INLINABLE sinh #-}+    {-# INLINE sinh #-}      tanh = fmap tanh-    {-# INLINABLE tanh #-}+    {-# INLINE tanh #-}      cosh = fmap cosh-    {-# INLINABLE cosh #-}+    {-# INLINE cosh #-}      asinh = fmap asinh-    {-# INLINABLE asinh #-}+    {-# INLINE asinh #-}      atanh = fmap atanh-    {-# INLINABLE atanh #-}+    {-# INLINE atanh #-}      acosh = fmap acosh-    {-# INLINABLE acosh #-}+    {-# INLINE acosh #-}      (**) = liftA2 (**)-    {-# INLINABLE (**) #-}+    {-# INLINE (**) #-}      logBase = liftA2 logBase-    {-# INLINABLE logBase #-}+    {-# INLINE logBase #-}  {-| Like 'Fold', but monadic. @@ -306,11 +313,11 @@         done' x = do             b <- done x             return $! f b-    {-# INLINABLE fmap #-}+    {-# INLINE fmap #-}  instance Monad m => Applicative (FoldM m a) where     pure b = FoldM (\() _ -> return ()) (return ()) (\() -> return b)-    {-# INLINABLE pure #-}+    {-# INLINE pure #-}      (FoldM stepL beginL doneL) <*> (FoldM stepR beginR doneR) =         let step (Pair xL xR) a = do@@ -326,7 +333,7 @@                 x <- doneR xR                 return $! f x         in  FoldM step begin done-    {-# INLINABLE (<*>) #-}+    {-# INLINE (<*>) #-}  instance Monad m => Profunctor (FoldM m) where     rmap = fmap@@ -334,97 +341,97 @@  instance (Monoid b, Monad m) => Monoid (FoldM m a b) where     mempty = pure mempty-    {-# INLINABLE mempty #-}+    {-# INLINE mempty #-}      mappend = liftA2 mappend-    {-# INLINABLE mappend #-}+    {-# INLINE mappend #-}  instance (Monad m, Num b) => Num (FoldM m a b) where     fromInteger = pure . fromInteger-    {-# INLINABLE fromInteger #-}+    {-# INLINE fromInteger #-}      negate = fmap negate-    {-# INLINABLE negate #-}+    {-# INLINE negate #-}      abs = fmap abs-    {-# INLINABLE abs #-}+    {-# INLINE abs #-}      signum = fmap signum-    {-# INLINABLE signum #-}+    {-# INLINE signum #-}      (+) = liftA2 (+)-    {-# INLINABLE (+) #-}+    {-# INLINE (+) #-}      (*) = liftA2 (*)-    {-# INLINABLE (*) #-}+    {-# INLINE (*) #-}      (-) = liftA2 (-)-    {-# INLINABLE (-) #-}+    {-# INLINE (-) #-}  instance (Monad m, Fractional b) => Fractional (FoldM m a b) where     fromRational = pure . fromRational-    {-# INLINABLE fromRational #-}+    {-# INLINE fromRational #-}      recip = fmap recip-    {-# INLINABLE recip #-}+    {-# INLINE recip #-}      (/) = liftA2 (/)-    {-# INLINABLE (/) #-}+    {-# INLINE (/) #-}  instance (Monad m, Floating b) => Floating (FoldM m a b) where     pi = pure pi-    {-# INLINABLE pi #-}+    {-# INLINE pi #-}      exp = fmap exp-    {-# INLINABLE exp #-}+    {-# INLINE exp #-}      sqrt = fmap sqrt-    {-# INLINABLE sqrt #-}+    {-# INLINE sqrt #-}      log = fmap log-    {-# INLINABLE log #-}+    {-# INLINE log #-}      sin = fmap sin-    {-# INLINABLE sin #-}+    {-# INLINE sin #-}      tan = fmap tan-    {-# INLINABLE tan #-}+    {-# INLINE tan #-}      cos = fmap cos-    {-# INLINABLE cos #-}+    {-# INLINE cos #-}      asin = fmap sin-    {-# INLINABLE asin #-}+    {-# INLINE asin #-}      atan = fmap atan-    {-# INLINABLE atan #-}+    {-# INLINE atan #-}      acos = fmap acos-    {-# INLINABLE acos #-}+    {-# INLINE acos #-}      sinh = fmap sinh-    {-# INLINABLE sinh #-}+    {-# INLINE sinh #-}      tanh = fmap tanh-    {-# INLINABLE tanh #-}+    {-# INLINE tanh #-}      cosh = fmap cosh-    {-# INLINABLE cosh #-}+    {-# INLINE cosh #-}      asinh = fmap asinh-    {-# INLINABLE asinh #-}+    {-# INLINE asinh #-}      atanh = fmap atanh-    {-# INLINABLE atanh #-}+    {-# INLINE atanh #-}      acosh = fmap acosh-    {-# INLINABLE acosh #-}+    {-# INLINE acosh #-}      (**) = liftA2 (**)-    {-# INLINABLE (**) #-}+    {-# INLINE (**) #-}      logBase = liftA2 logBase-    {-# INLINABLE logBase #-}+    {-# INLINE logBase #-}  -- | Apply a strict left 'Fold' to a 'Foldable' container fold :: Foldable f => Fold a b -> f a -> b@@ -543,11 +550,43 @@ sum = Fold (+) 0 id {-# INLINABLE sum #-} --- | Computes the product all elements+-- | Computes the product of all elements product :: Num a => Fold a a product = Fold (*) 1 id {-# INLINABLE product #-} +-- | Compute a numerically stable arithmetic mean of all elements+mean :: Fractional a => Fold a a+mean = Fold step begin done+  where+    begin = Pair 0 0+    step (Pair x n) y = Pair ((x * n + y) / (n + 1)) (n + 1)+    done (Pair x _) = x+{-# INLINABLE mean #-}++-- | Compute a numerically stable (population) variance over all elements+variance :: Fractional a => Fold a a+variance = Fold step begin done+  where+    begin = Pair3 0 0 0++    step (Pair3 n mean_ m2) x = Pair3 n' mean' m2'+      where+        n'     = n + 1+        mean'  = (n * mean_ + x) / (n + 1)+        delta  = x - mean_+        m2'    = m2 + delta * delta * n / (n + 1)++    done (Pair3 n _ m2) = m2 / n+{-# INLINABLE variance #-}++{-| Compute a numerically stable (population) standard deviation over all+    elements+-}+std :: Floating a => Fold a a+std = sqrt variance+{-# INLINABLE std #-}+ -- | Computes the maximum element maximum :: Ord a => Fold a (Maybe a) maximum = _Fold1 max@@ -853,8 +892,7 @@  -- | Upgrade a monadic fold to accept the 'FoldM' type impurely-    :: Monad m-    => (forall x . (x -> a -> m x) -> m x -> (x -> m b) -> r)+    :: (forall x . (x -> a -> m x) -> m x -> (x -> m b) -> r)     -> FoldM m a b     -> r impurely f (FoldM step begin done) = f step begin done@@ -901,8 +939,9 @@ {- | Shift a 'FoldM' from one monad to another with a morphism such as 'lift' or 'liftIO';      the effect is the same as 'Control.Monad.Morph.hoist'. -}-hoists :: Monad m => (forall x . m x -> n x) -> FoldM m a b -> FoldM n a b+hoists :: (forall x . m x -> n x) -> FoldM m a b -> FoldM n a b hoists phi (FoldM step begin done) = FoldM (\a b -> phi (step a b)) (phi begin) (phi . done)+{-# INLINABLE hoists #-}  {-| Allows to continue feeding a 'FoldM' even after passing it to a function that closes it.@@ -925,6 +964,7 @@     step_ mx a = Just' (case mx of         Nothing' -> a         Just' x -> step x a)+{-# INLINABLE _Fold1 #-}  {-| @(premap f folder)@ returns a new 'Fold' where f is applied at each step @@ -1010,6 +1050,26 @@     step' = flip (appEndo . getDual . getConst . k (Const . Dual . Endo . flip step)) {-# INLINABLE handles #-} +{- | @{foldOver f folder xs} folds all values from a Lens, Traversal, Prism or Fold with the given folder++>>> foldOver (_Just . both) L.sum (Just (2, 3))+5++>>> foldOver (_Just . both) L.sum Nothing+0++> L.foldOver f folder xs == L.fold folder (xs^..f)++> L.foldOver (folded.f) folder == L.fold (handles f folder)++> L.foldOver folded == L.fold++-}+foldOver :: Handler s a -> Fold a b -> s -> b+foldOver l (Fold step begin done) =+  done . flip appEndo begin . getDual . getConst . l (Const . Dual . Endo . flip step)+{-# INLINABLE foldOver #-}+ {-| > instance Monad m => Monoid (EndoM m a) where >     mempty = EndoM return@@ -1019,7 +1079,10 @@  instance Monad m => Monoid (EndoM m a) where     mempty = EndoM return+    {-# INLINE mempty #-}+     mappend (EndoM f) (EndoM g) = EndoM (f <=< g)+    {-# INLINE mappend #-}  {-| A Handler for the upstream input of `FoldM` @@ -1046,12 +1109,26 @@ > > handlesM t (f <*> x) = handlesM t f <*> handlesM t x -}-handlesM :: Monad m => HandlerM m a b -> FoldM m b r -> FoldM m a r+handlesM :: HandlerM m a b -> FoldM m b r -> FoldM m a r handlesM k (FoldM step begin done) = FoldM step' begin done   where     step' = flip (appEndoM . getDual . getConst . k (Const . Dual . EndoM . flip step)) {-# INLINABLE handlesM #-} +{- | @{foldOverM f folder xs} folds all values from a Lens, Traversal, Prism or Fold monadically with the given folder++> L.foldOverM (folded.f) folder == L.foldM (handlesM f folder)++> L.foldOverM folded == L.foldM++-}+foldOverM :: Monad m => HandlerM m s a -> FoldM m a b -> s -> m b+foldOverM l (FoldM step begin done) s = do+  b <- begin+  r <- (flip appEndoM b . getDual . getConst . l (Const . Dual . EndoM . flip step)) s+  done r+{-# INLINABLE foldOverM #-}+ {-| > folded :: Foldable t => Fold (t a) a >@@ -1061,6 +1138,7 @@     :: (Contravariant f, Applicative f, Foldable t)     => (a -> f a) -> (t a -> f (t a)) folded k ts = contramap (\_ -> ()) (F.traverse_ k ts)+{-# INLINABLE folded #-}  {-| >>> fold (handles (filtered even) sum) [1..10]
src/Control/Foldl/ByteString.hs view
@@ -3,6 +3,7 @@ module Control.Foldl.ByteString (     -- * Folding       fold+    , foldM      -- * Folds     , head@@ -28,7 +29,7 @@     , module Data.Word     ) where -import Control.Foldl (Fold)+import Control.Foldl (Fold, FoldM) import Control.Foldl.Internal (Maybe'(..), lazy, strict, Either'(..), hush) import qualified Control.Foldl as L import Data.ByteString (ByteString)@@ -43,6 +44,17 @@ fold :: Fold ByteString a -> Lazy.ByteString -> a fold (L.Fold step begin done) as = done (Lazy.foldlChunks step begin as) {-# INLINABLE fold #-}++-- | Apply a strict monadic left 'FoldM' to a lazy bytestring+foldM :: Monad m => FoldM m ByteString a -> Lazy.ByteString -> m a+foldM (L.FoldM step begin done) as = do+    x <- Lazy.foldlChunks step' begin as+    done x+  where+    step' mx bs = do+      x <- mx+      x `seq` step x bs+{-# INLINABLE foldM #-}  {-| Get the first byte of a byte stream or return 'Nothing' if the stream is     empty
src/Control/Foldl/Text.hs view
@@ -3,6 +3,7 @@ module Control.Foldl.Text (     -- * Folding       fold+    , foldM      -- * Folds     , head@@ -27,7 +28,7 @@     , module Data.Text     ) where -import Control.Foldl (Fold)+import Control.Foldl (Fold, FoldM) import Control.Foldl.Internal (Maybe'(..), lazy, strict, Either'(..), hush) import qualified Control.Foldl as L import Data.Text (Text)@@ -40,6 +41,17 @@ fold :: Fold Text a -> Lazy.Text -> a fold (L.Fold step begin done) as = done (Lazy.foldlChunks step begin as) {-# INLINABLE fold #-}++-- | Apply a strict monadic left 'FoldM' to lazy text+foldM :: Monad m => FoldM m Text a -> Lazy.Text -> m a+foldM (L.FoldM step begin done) as = do+    x <- Lazy.foldlChunks step' begin as+    done x+  where+    step' mx bs = do+      x <- mx+      x `seq` step x bs+{-# INLINABLE foldM #-}  {-| Get the first character of a text stream or return 'Nothing' if the stream     is empty