The Foldable class represents data structures that can be reduced to a summary value one element at a time. Strict left-associative folds are a good fit for space-efficient reduction, while lazy right-associative folds are a good fit for corecursive iteration, or for folds that short-circuit after processing an initial subsequence of the structure's elements.
Instances can be derived automatically by enabling the DeriveFoldable
extension. For example, a derived instance for a binary tree might be:
{-# LANGUAGE DeriveFoldable #-}
data Tree a = Empty
| Leaf a
| Node (Tree a) a (Tree a)
deriving FoldableA more detailed description can be found in the Overview section of
Data.Foldable#overview.
For the class laws see the Laws section of Data.Foldable#laws.
Methods
fold :: Monoid m => t m -> mGiven a structure with elements whose type is a Monoid, combine them via the monoid's
(<>)operator. This fold is right-associative and lazy in the accumulator. When you need a strict left-associative fold, use foldMap' instead, with id as the map.Examples
Basic usage:
Example1 expression fold [[1, 2, 3], [4, 5], [6], []][1,2,3,4,5,6]
Example1 expression fold $ Node (Leaf (Sum 1)) (Sum 3) (Leaf (Sum 5))Sum {getSum = 9}
Folds of unbounded structures do not terminate when the monoid's
(<>)operator is strict:Example1 expression fold (repeat Nothing)* Hangs forever *
Lazy corecursive folds of unbounded structures are fine:
Example2 expressions take 12 $ fold $ map (\i -> [i..i+2]) [0..][0,1,2,1,2,3,2,3,4,3,4,5]sum $ take 4000000 $ fold $ map (\i -> [i..i+2]) [0..]2666668666666
foldMap :: Monoid m => (a -> m) -> t a -> mMap each element of the structure into a monoid, and combine the results with
(<>). This fold is right-associative and lazy in the accumulator. For strict left-associative folds consider foldMap' instead.Examples
Basic usage:
Example1 expression foldMap Sum [1, 3, 5]Sum {getSum = 9}
Example1 expression foldMap Product [1, 3, 5]Product {getProduct = 15}
Example1 expression foldMap (replicate 3) [1, 2, 3][1,1,1,2,2,2,3,3,3]
When a Monoid's
(<>)is lazy in its second argument, foldMap can return a result even from an unbounded structure. For example, lazy accumulation enables Data.ByteString.Builder to efficiently serialise large data structures and produce the output incrementally:Example5 expressions import qualified Data.ByteString.Lazy as Limport qualified Data.ByteString.Builder as Blet bld :: Int -> B.Builder; bld i = B.intDec i <> B.word8 0x20let lbs = B.toLazyByteString $ foldMap bld [0..]L.take 64 lbs"0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24"
foldMap' :: Monoid m => (a -> m) -> t a -> mA left-associative variant of foldMap that is strict in the accumulator. Use this method for strict reduction when partial results are merged via
(<>).Examples
Define a Monoid over finite bit strings under
xor. Use it to strictly compute thexorof a list of Int values.Example11 expressions :set -XGeneralizedNewtypeDerivingimport Data.Bits (Bits, FiniteBits, xor, zeroBits)import Data.Foldable (foldMap')import Numeric (showHex)newtype X a = X a deriving (Eq, Bounded, Enum, Bits, FiniteBits)instance Bits a => Semigroup (X a) where X a <> X b = X (a `xor` b)instance Bits a => Monoid (X a) where mempty = X zeroBitslet bits :: [Int]; bits = [0xcafe, 0xfeed, 0xdeaf, 0xbeef, 0x5411](\ (X a) -> showString "0x" . showHex a $ "") $ foldMap' X bits"0x42"
foldr :: (a -> b -> b) -> b -> t a -> bRight-associative fold of a structure, lazy in the accumulator.
In the case of lists, foldr, when applied to a binary operator, a starting value (typically the right-identity of the operator), and a list, reduces the list using the binary operator, from right to left:
foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...)Note that since the head of the resulting expression is produced by an application of the operator to the first element of the list, given an operator lazy in its right argument, foldr can produce a terminating expression from an unbounded list.
For a general Foldable structure this should be semantically identical to,
foldr f z = foldr f z . toListExamples
Basic usage:
Example1 expression foldr (||) False [False, True, False]True
Example1 expression foldr (||) False []False
Example1 expression foldr (\c acc -> acc ++ [c]) "foo" ['a', 'b', 'c', 'd']"foodcba"
Infinite structures
⚠️ Applying foldr to infinite structures usually doesn't terminate.
It may still terminate under one of the following conditions:
the folding function is short-circuiting
the folding function is lazy on its second argument
Short-circuiting
(||)short-circuits on True values, so the following terminates because there is a True value finitely far from the left side:Example1 expression foldr (||) False (True : repeat False)True
But the following doesn't terminate:
Example1 expression foldr (||) False (repeat False ++ [True])* Hangs forever *
Laziness in the second argument
Applying foldr to infinite structures terminates when the operator is lazy in its second argument (the initial accumulator is never used in this case, and so could be left undefined, but
[]is more clear):Example1 expression take 5 $ foldr (\i acc -> i : fmap (+3) acc) [] (repeat 1)[1,4,7,10,13]
foldl' :: (b -> a -> b) -> b -> t a -> bLeft-associative fold of a structure but with strict application of the operator.
This ensures that each step of the fold is forced to Weak Head Normal Form before being applied, avoiding the collection of thunks that would otherwise occur. This is often what you want to strictly reduce a finite structure to a single strict result (e.g. sum).
For a general Foldable structure this should be semantically identical to,
foldl' f z = foldl' f z . toListtoList :: t a -> [a]List of elements of a structure, from left to right. If the entire list is intended to be reduced via a fold, just fold the structure directly bypassing the list.
Examples
Basic usage:
Example1 expression toList Nothing[]
Example1 expression toList (Just 42)[42]
Example1 expression toList (Left "foo")[]
Example1 expression toList (Node (Leaf 5) 17 (Node Empty 12 (Leaf 8)))[5,17,12,8]
For lists, toList is the identity:
Example1 expression toList [1, 2, 3][1,2,3]
null :: t a -> BoolTest whether the structure is empty. The default implementation is Left-associative and lazy in both the initial element and the accumulator. Thus optimised for structures where the first element can be accessed in constant time. Structures where this is not the case should have a non-default implementation.
Examples
Basic usage:
Example1 expression null []True
Example1 expression null [1]False
null is expected to terminate even for infinite structures. The default implementation terminates provided the structure is bounded on the left (there is a leftmost element).
Example1 expression null [1..]False
length :: t a -> IntReturns the size/length of a finite structure as an Int. The default implementation just counts elements starting with the leftmost. Instances for structures that can compute the element count faster than via element-by-element counting, should provide a specialised implementation.
Examples
Basic usage:
Example1 expression length []0
Example2 expressions length ['a', 'b', 'c']3length [1..]* Hangs forever *
Instances70Foldable, …
Foldable ComplexDefined in base-4.20.2.0 · Data.ComplexFoldable FirstDefined in base-4.20.2.0 · Data.SemigroupFoldable LastDefined in base-4.20.2.0 · Data.SemigroupFoldable MaxDefined in base-4.20.2.0 · Data.SemigroupFoldable MinDefined in base-4.20.2.0 · Data.SemigroupFoldable SCCDefined in containers-0.7 · Data.GraphFoldable IntMapDefined in containers-0.7 · Data.IntMap.InternalFolds in order of increasing key.
Foldable DigitDefined in containers-0.7 · Data.Sequence.InternalFoldable ElemDefined in containers-0.7 · Data.Sequence.InternalFoldable FingerTreeDefined in containers-0.7 · Data.Sequence.InternalFoldable NodeDefined in containers-0.7 · Data.Sequence.InternalFoldable SeqDefined in containers-0.7 · Data.Sequence.InternalFoldable ViewLDefined in containers-0.7 · Data.Sequence.InternalFoldable ViewRDefined in containers-0.7 · Data.Sequence.InternalFoldable SetDefined in containers-0.7 · Data.Set.InternalFolds in order of increasing key.
Foldable TreeDefined in containers-0.7 · Data.TreeFolds in preorder
Foldable MaybeSDefined in containers-0.7 · Utils.Containers.Internal.StrictMaybeFoldable NonEmptyDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable IdentityDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.Functor.IdentityFoldable FirstDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable LastDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable DownDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable DualDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable ProductDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable SumDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable ZipListDefined in ghc-internal-9.1003.0 · GHC.Internal.Functor.ZipListFoldable Par1Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable MaybeDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable SoloDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable HashedDefined in hashable-1.4.7.0 · Data.Hashable.ClassFoldable TyVarBndrDefined in template-haskell-2.22.0.0 · Language.Haskell.TH.SyntaxFoldable HashSetDefined in unordered-containers-0.2.21 · Data.HashSet.InternalFoldable []Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable ProxyDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable U1Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable UAddrDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable UCharDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable UDoubleDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable UFloatDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable UIntDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable UWordDefined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable V1Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable (Arg a)Defined in base-4.20.2.0 · Data.SemigroupFoldable (Map k)Defined in containers-0.7 · Data.Map.InternalFolds in order of increasing key.
Foldable (Array i)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable (Either a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable (Tuple2 a)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable (HashMap k)Defined in unordered-containers-0.2.21 · Data.HashMap.InternalFoldable f => Foldable (Lift f)Defined in transformers-0.6.1.1 · Control.Applicative.LiftFoldable f => Foldable (MaybeT f)Defined in transformers-0.6.1.1 · Control.Monad.Trans.MaybeFoldable m => Foldable (CatchT m)Defined in exceptions-0.10.9 · Control.Monad.Catch.PureFoldable (Const m)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Functor.ConstFoldable (Constant a)Defined in transformers-0.6.1.1 · Data.Functor.ConstantFoldable f => Foldable (Ap f)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable f => Foldable (Alt f)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable f => Foldable (Rec1 f)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable f => Foldable (Backwards f)Defined in transformers-0.6.1.1 · Control.Applicative.BackwardsDerived instance.
Foldable f => Foldable (ExceptT e f)Defined in transformers-0.6.1.1 · Control.Monad.Trans.ExceptFoldable f => Foldable (IdentityT f)Defined in transformers-0.6.1.1 · Control.Monad.Trans.IdentityFoldable f => Foldable (WriterT w f)Defined in transformers-0.6.1.1 · Control.Monad.Trans.Writer.LazyFoldable f => Foldable (WriterT w f)Defined in transformers-0.6.1.1 · Control.Monad.Trans.Writer.StrictFoldable f => Foldable (Reverse f)Defined in transformers-0.6.1.1 · Data.Functor.ReverseFold from right to left.
Foldable (K1 i c)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Foldable(Foldable f, Foldable g) => Foldable (Product f g)Defined in base-4.20.2.0 · Data.Functor.Product(Foldable f, Foldable g) => Foldable (Sum f g)Defined in base-4.20.2.0 · Data.Functor.Sum(Foldable f, Foldable g) => Foldable (f :*: g)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Foldable(Foldable f, Foldable g) => Foldable (f :+: g)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.FoldableFoldable f => Foldable (M1 i c f)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Foldable(Foldable f, Foldable g) => Foldable (Compose f g)Defined in base-4.20.2.0 · Data.Functor.Compose(Foldable f, Foldable g) => Foldable (f :.: g)Defined in ghc-internal-9.1003.0 · GHC.Internal.Data.Foldable