foldl 1.4.12 → 1.4.13
raw patch · 8 files changed
+253/−48 lines, 8 filesdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Control.Foldl.NonEmpty: Fold1 :: (a -> Fold a b) -> Fold1 a b
+ Control.Foldl.NonEmpty: data Fold1 a b
+ Control.Foldl.NonEmpty: fold1 :: Fold1 a b -> NonEmpty a -> b
+ Control.Foldl.NonEmpty: fromFold :: Fold a b -> Fold1 a b
+ Control.Foldl.NonEmpty: head :: Fold1 a a
+ Control.Foldl.NonEmpty: instance Data.Profunctor.Unsafe.Profunctor Control.Foldl.NonEmpty.Fold1
+ Control.Foldl.NonEmpty: instance GHC.Base.Applicative (Control.Foldl.NonEmpty.Fold1 a)
+ Control.Foldl.NonEmpty: instance GHC.Base.Functor (Control.Foldl.NonEmpty.Fold1 a)
+ Control.Foldl.NonEmpty: instance GHC.Base.Monoid b => GHC.Base.Monoid (Control.Foldl.NonEmpty.Fold1 a b)
+ Control.Foldl.NonEmpty: instance GHC.Base.Semigroup b => GHC.Base.Semigroup (Control.Foldl.NonEmpty.Fold1 a b)
+ Control.Foldl.NonEmpty: instance GHC.Float.Floating b => GHC.Float.Floating (Control.Foldl.NonEmpty.Fold1 a b)
+ Control.Foldl.NonEmpty: instance GHC.Num.Num b => GHC.Num.Num (Control.Foldl.NonEmpty.Fold1 a b)
+ Control.Foldl.NonEmpty: instance GHC.Real.Fractional b => GHC.Real.Fractional (Control.Foldl.NonEmpty.Fold1 a b)
+ Control.Foldl.NonEmpty: last :: Fold1 a a
+ Control.Foldl.NonEmpty: maximum :: Ord a => Fold1 a a
+ Control.Foldl.NonEmpty: maximumBy :: (a -> a -> Ordering) -> Fold1 a a
+ Control.Foldl.NonEmpty: minimum :: Ord a => Fold1 a a
+ Control.Foldl.NonEmpty: minimumBy :: (a -> a -> Ordering) -> Fold1 a a
+ Control.Foldl.NonEmpty: sconcat :: Semigroup a => Fold1 a a
- Control.Foldl: class Foldable (t :: Type -> Type)
+ Control.Foldl: class Foldable (t :: TYPE LiftedRep -> Type)
- Control.Foldl.ByteString: class Foldable (t :: Type -> Type)
+ Control.Foldl.ByteString: class Foldable (t :: TYPE LiftedRep -> Type)
- Control.Foldl.Text: class Foldable (t :: Type -> Type)
+ Control.Foldl.Text: class Foldable (t :: TYPE LiftedRep -> Type)
Files
- CHANGELOG.md +4/−0
- LICENSE +2/−2
- README.md +3/−3
- foldl.cabal +12/−11
- src/Control/Foldl.hs +32/−30
- src/Control/Foldl/NonEmpty.hs +200/−0
- src/Control/Foldl/Optics.hs +0/−1
- src/Control/Scanl.hs +0/−1
CHANGELOG.md view
@@ -1,3 +1,7 @@+1.4.13++* New "Control.Foldl.NonEmpty" module for folding non-empty containers+ 1.4.12 * `Data.Functor.Extend.Extended` instances for `Fold` / `FoldM`
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2013 Gabriel Gonzalez+Copyright (c) 2013 Gabriella Gonzalez All rights reserved. Redistribution and use in source and binary forms, with or without modification,@@ -8,7 +8,7 @@ * 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+ * Neither the name of Gabriella Gonzalez nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission.
README.md view
@@ -136,7 +136,7 @@ ## Development Status -[](https://travis-ci.org/Gabriel439/Haskell-Foldl-Library)+[](https://travis-ci.org/Gabriella439/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@@ -144,7 +144,7 @@ ## License (BSD 3-clause) -Copyright (c) 2016 Gabriel Gonzalez+Copyright (c) 2016 Gabriella Gonzalez All rights reserved. Redistribution and use in source and binary forms, with or without modification,@@ -157,7 +157,7 @@ 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+* Neither the name of Gabriella Gonzalez nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission.
foldl.cabal view
@@ -1,13 +1,13 @@ Name: foldl-Version: 1.4.12+Version: 1.4.13 Cabal-Version: >=1.10 Build-Type: Simple License: BSD3 License-File: LICENSE-Copyright: 2013 Gabriel Gonzalez-Author: Gabriel Gonzalez-Maintainer: Gabriel439@gmail.com-Bug-Reports: https://github.com/Gabriel439/Haskell-Foldl-Library/issues+Copyright: 2013 Gabriella Gonzalez+Author: Gabriella Gonzalez+Maintainer: GenuineGabriella@gmail.com+Bug-Reports: https://github.com/Gabriella439/Haskell-Foldl-Library/issues Synopsis: Composable, streaming, and efficient left folds Description: This library provides strict left folds that stream in constant memory, and you can combine folds using @Applicative@ style to derive new@@ -19,21 +19,21 @@ README.md Source-Repository head Type: git- Location: https://github.com/Gabriel439/Haskell-Foldl-Library+ Location: https://github.com/Gabriella439/Haskell-Foldl-Library Library HS-Source-Dirs: src Build-Depends:- base >= 4.8 && < 5 ,+ base >= 4.11.0.0 && < 5 , bytestring >= 0.9.2.1 && < 0.12, random >= 1.2 && < 1.3 , primitive < 0.8 ,- text >= 0.11.2.0 && < 1.3 ,- transformers >= 0.2.0.0 && < 0.6 ,- vector >= 0.7 && < 0.13,+ text >= 0.11.2.0 && < 2.1 ,+ transformers >= 0.2.0.0 && < 0.7 ,+ vector >= 0.7 && < 0.14, containers >= 0.5.0.0 && < 0.7 , unordered-containers < 0.3 ,- hashable < 1.4 ,+ hashable < 1.5 , contravariant < 1.6 , profunctors < 5.7 , semigroupoids >= 1.0 && < 5.4 ,@@ -44,6 +44,7 @@ Exposed-Modules: Control.Foldl, Control.Foldl.ByteString,+ Control.Foldl.NonEmpty Control.Foldl.Text, Control.Scanl Other-Modules:
src/Control/Foldl.hs view
@@ -3,32 +3,35 @@ Import this module qualified to avoid clashing with the Prelude: ->>> import qualified Control.Foldl as L+>>> import qualified Control.Foldl as Foldl Use 'fold' to apply a 'Fold' to a list: ->>> L.fold L.sum [1..100]+>>> Foldl.fold Foldl.sum [1..100] 5050 'Fold's are 'Applicative's, so you can combine them using 'Applicative' combinators: >>> import Control.Applicative->>> let average = (/) <$> L.sum <*> L.genericLength+>>> let average = (/) <$> Foldl.sum <*> Foldl.genericLength - Taking the sum, the sum of squares, ..., upto the sum of x^5+ … or you can use @do@ notation if you enable the @ApplicativeDo@ language+ extension: ->>> import Data.Traversable->>> let powerSums = sequenceA [L.premap (^n) L.sum | n <- [1..5]]->>> L.fold powerSums [1..10]-[55,385,3025,25333,220825]+>>> :set -XApplicativeDo+>>> let average = do total <- Foldl.sum; count <- Foldl.genericLength; return (total / count) + … or you can use the fact that the `Fold` type implements `Num` to do this:++>>> let average = Foldl.sum / Foldl.genericLength+ These combined folds will still traverse the list only once, streaming efficiently over the list in constant space without space leaks: ->>> L.fold average [1..10000000]+>>> Foldl.fold average [1..10000000] 5000000.5->>> L.fold ((,) <$> L.minimum <*> L.maximum) [1..10000000]+>>> Foldl.fold ((,) <$> Foldl.minimum <*> Foldl.maximum) [1..10000000] (Just 1,Just 10000000) You might want to try enabling the @-flate-dmd-anal@ flag when compiling@@ -158,7 +161,6 @@ import Data.Map.Strict (Map, alter) import Data.Maybe (fromMaybe) import Data.Monoid hiding ((<>))-import Data.Semigroup (Semigroup(..)) import Data.Semigroupoid (Semigroupoid) import Data.Functor.Extend (Extend(..)) import Data.Profunctor@@ -204,7 +206,7 @@ {- $setup ->>> import qualified Control.Foldl as L+>>> import qualified Control.Foldl as Foldl >>> _2 f (x, y) = fmap (\i -> (x, i)) (f y) @@ -529,7 +531,7 @@ {-| Convert a strict left 'Fold' into a scan - >>> L.scan L.length [1..5]+ >>> Foldl.scan Foldl.length [1..5] [0,1,2,3,4,5] -} scan :: Fold a b -> [a] -> [b]@@ -543,7 +545,7 @@ \"Prescan\" means that the last element of the scan is not included - >>> L.prescan L.length [1..5]+ >>> Foldl.prescan Foldl.length [1..5] [0,1,2,3,4] -} prescan :: Traversable t => Fold a b -> t a -> t b@@ -560,7 +562,7 @@ \"Postscan\" means that the first element of the scan is not included - >>> L.postscan L.length [1..5]+ >>> Foldl.postscan Foldl.length [1..5] [1,2,3,4,5] -} postscan :: Traversable t => Fold a b -> t a -> t b@@ -1175,10 +1177,10 @@ > fold (premap f folder) list = fold folder (List.map f list) ->>> fold (premap Sum L.mconcat) [1..10]+>>> fold (premap Sum Foldl.mconcat) [1..10] Sum {getSum = 55} ->>> fold L.mconcat (List.map Sum [1..10])+>>> fold Foldl.mconcat (List.map Sum [1..10]) Sum {getSum = 55} > premap id = id@@ -1268,10 +1270,10 @@ > fold (drop n folder) list = fold folder (Data.List.genericDrop n list) ->>> L.fold (L.drop 3 L.sum) [10, 20, 30, 1, 2, 3]+>>> Foldl.fold (Foldl.drop 3 Foldl.sum) [10, 20, 30, 1, 2, 3] 6 ->>> L.fold (L.drop 10 L.sum) [10, 20, 30, 1, 2, 3]+>>> Foldl.fold (Foldl.drop 10 Foldl.sum) [10, 20, 30, 1, 2, 3] 0 -} @@ -1289,10 +1291,10 @@ > foldM (dropM n folder) list = foldM folder (Data.List.genericDrop n list) ->>> L.foldM (L.dropM 3 (L.generalize L.sum)) [10, 20, 30, 1, 2, 3]+>>> Foldl.foldM (Foldl.dropM 3 (Foldl.generalize Foldl.sum)) [10, 20, 30, 1, 2, 3] 6 ->>> L.foldM (L.dropM 10 (L.generalize L.sum)) [10, 20, 30, 1, 2, 3]+>>> Foldl.foldM (Foldl.dropM 10 (Foldl.generalize Foldl.sum)) [10, 20, 30, 1, 2, 3] 0 -} @@ -1329,7 +1331,7 @@ >>> fold (handles (filtered even) sum) [1..10] 30 ->>> fold (handles _2 L.mconcat) [(1,"Hello "),(2,"World"),(3,"!")]+>>> fold (handles _2 Foldl.mconcat) [(1,"Hello "),(2,"World"),(3,"!")] "Hello World!" > handles id = id@@ -1348,17 +1350,17 @@ {- | @(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))+>>> foldOver (_Just . both) Foldl.sum (Just (2, 3)) 5 ->>> foldOver (_Just . both) L.sum Nothing+>>> foldOver (_Just . both) Foldl.sum Nothing 0 -> L.foldOver f folder xs == L.fold folder (xs^..f)+> Foldl.foldOver f folder xs == Foldl.fold folder (xs^..f) -> L.foldOver (folded.f) folder == L.fold (handles f folder)+> Foldl.foldOver (folded.f) folder == Foldl.fold (handles f folder) -> L.foldOver folded == L.fold+> Foldl.foldOver folded == Foldl.fold -} foldOver :: Handler s a -> Fold a b -> s -> b@@ -1417,9 +1419,9 @@ {- | @(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)+> Foldl.foldOverM (folded.f) folder == Foldl.foldM (handlesM f folder) -> L.foldOverM folded == L.foldM+> Foldl.foldOverM folded == Foldl.foldM -} foldOverM :: Monad m => HandlerM m s a -> FoldM m a b -> s -> m b@@ -1444,7 +1446,7 @@ >>> fold (handles (filtered even) sum) [1..10] 30 ->>> foldM (handlesM (filtered even) (L.mapM_ print)) [1..10]+>>> foldM (handlesM (filtered even) (Foldl.mapM_ print)) [1..10] 2 4 6
+ src/Control/Foldl/NonEmpty.hs view
@@ -0,0 +1,200 @@+{-| This module provides a `Fold1` type that is a \"non-empty\" analog of the+ `Fold` type, meaning that it requires at least one input element in order to+ produce a result++ This module does not provide all of the same utilities as the+ "Control.Foldl" module. Instead, this module only provides the utilities+ which can make use of the non-empty input guarantee (e.g. `head`). For+ all other utilities you can convert them from the equivalent `Fold` using+ `fromFold`.+-}++module Control.Foldl.NonEmpty where++import Control.Applicative (liftA2)+import Control.Foldl (Fold(..))+import Data.List.NonEmpty (NonEmpty(..))+import Data.Profunctor (Profunctor(..))+import Prelude hiding (head, last, minimum, maximum)++import qualified Control.Foldl as Foldl++{-| A `Fold1` is like a `Fold` except that it consumes at least one input+ element+-}+data Fold1 a b = Fold1 (a -> Fold a b)++instance Functor (Fold1 a) where+ fmap f (Fold1 k) = Fold1 (fmap (fmap f) k)+ {-# INLINE fmap #-}++instance Profunctor Fold1 where+ lmap f (Fold1 k) = Fold1 k'+ where+ k' a = lmap f (k (f a))+ {-# INLINE lmap #-}++ rmap = fmap+ {-# INLINE rmap #-}++instance Applicative (Fold1 a) where+ pure b = Fold1 (pure (pure b))+ {-# INLINE pure #-}++ Fold1 l <*> Fold1 r = Fold1 (liftA2 (<*>) l r)+ {-# INLINE (<*>) #-}++instance Semigroup b => Semigroup (Fold1 a b) where+ (<>) = liftA2 (<>)+ {-# INLINE (<>) #-}++instance Monoid b => Monoid (Fold1 a b) where+ mempty = pure mempty+ {-# INLINE mempty #-}++ mappend = liftA2 mappend+ {-# INLINE mappend #-}++instance Num b => Num (Fold1 a b) where+ fromInteger = pure . fromInteger+ {-# INLINE fromInteger #-}++ negate = fmap negate+ {-# INLINE negate #-}++ abs = fmap abs+ {-# INLINE abs #-}++ signum = fmap signum+ {-# INLINE signum #-}++ (+) = liftA2 (+)+ {-# INLINE (+) #-}++ (*) = liftA2 (*)+ {-# INLINE (*) #-}++ (-) = liftA2 (-)+ {-# INLINE (-) #-}++instance Fractional b => Fractional (Fold1 a b) where+ fromRational = pure . fromRational+ {-# INLINE fromRational #-}++ recip = fmap recip+ {-# INLINE recip #-}++ (/) = liftA2 (/)+ {-# INLINE (/) #-}++instance Floating b => Floating (Fold1 a b) where+ pi = pure pi+ {-# INLINE pi #-}++ exp = fmap exp+ {-# INLINE exp #-}++ sqrt = fmap sqrt+ {-# INLINE sqrt #-}++ log = fmap log+ {-# INLINE log #-}++ sin = fmap sin+ {-# INLINE sin #-}++ tan = fmap tan+ {-# INLINE tan #-}++ cos = fmap cos+ {-# INLINE cos #-}++ asin = fmap asin+ {-# INLINE asin #-}++ atan = fmap atan+ {-# INLINE atan #-}++ acos = fmap acos+ {-# INLINE acos #-}++ sinh = fmap sinh+ {-# INLINE sinh #-}++ tanh = fmap tanh+ {-# INLINE tanh #-}++ cosh = fmap cosh+ {-# INLINE cosh #-}++ asinh = fmap asinh+ {-# INLINE asinh #-}++ atanh = fmap atanh+ {-# INLINE atanh #-}++ acosh = fmap acosh+ {-# INLINE acosh #-}++ (**) = liftA2 (**)+ {-# INLINE (**) #-}++ logBase = liftA2 logBase+ {-# INLINE logBase #-}++-- | Apply a strict left `Fold1` to a `NonEmpty` list+fold1 :: Fold1 a b -> NonEmpty a -> b+fold1 (Fold1 k) (a :| as) = Foldl.fold (k a) as+{-# INLINABLE fold1 #-}++-- | Promote any `Fold` to an equivalent `Fold1`+fromFold :: Fold a b -> Fold1 a b+fromFold (Fold step begin done) = Fold1 (\a -> Fold step (step begin a) done)+{-# INLINABLE fromFold #-}++-- | Fold all values within a non-empty container using (`<>`)+sconcat :: Semigroup a => Fold1 a a+sconcat = Fold1 (\begin -> Fold (<>) begin id)+{-# INLINABLE sconcat #-}++-- | Get the first element of a non-empty container+head :: Fold1 a a+head = Fold1 (\begin -> Fold step begin id)+ where+ step a _ = a+{-# INLINABLE head #-}++-- | Get the last element of a non-empty container+last :: Fold1 a a+last = Fold1 (\begin -> Fold step begin id)+ where+ step _ a = a+{-# INLINABLE last #-}++-- | Computes the maximum element+maximum :: Ord a => Fold1 a a+maximum = Fold1 (\begin -> Fold max begin id)+{-# INLINABLE maximum #-}++-- | Computes the maximum element with respect to the given comparison function+maximumBy :: (a -> a -> Ordering) -> Fold1 a a+maximumBy cmp = Fold1 (\begin -> Fold max' begin id)+ where+ max' x y = case cmp x y of+ GT -> x+ _ -> y+{-# INLINABLE maximumBy #-}++-- | Computes the minimum element+minimum :: Ord a => Fold1 a a+minimum = Fold1 (\begin -> Fold min begin id)+{-# INLINABLE minimum #-}++-- | Computes the minimum element with respect to the given comparison function+minimumBy :: (a -> a -> Ordering) -> Fold1 a a+minimumBy cmp = Fold1 (\begin -> Fold min' begin id)+ where+ min' x y = case cmp x y of+ GT -> y+ _ -> x+{-# INLINABLE minimumBy #-}
src/Control/Foldl/Optics.hs view
@@ -2,7 +2,6 @@ module Control.Foldl.Optics where import Data.Profunctor-import Control.Applicative type Prism s t a b = forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t)
src/Control/Scanl.hs view
@@ -74,7 +74,6 @@ import Data.Functor.Identity import Data.Monoid hiding ((<>)) import Data.Profunctor-import Data.Semigroup (Semigroup(..)) import Data.Traversable import Data.Tuple (swap) import Prelude hiding ((.), id, scanr)