Bifoldable identifies foldable structures with two different varieties
of elements (as opposed to Foldable, which has one variety of element).
Common examples are Either and (,):
instance Bifoldable Either where
bifoldMap f _ (Left a) = f a
bifoldMap _ g (Right b) = g b
instance Bifoldable (,) where
bifoldr f g z (a, b) = f a (g b z)Some examples below also use the following BiList to showcase empty
Bifoldable behaviors when relevant (Either and (,) containing always exactly
resp. 1 and 2 elements):
data BiList a b = BiList [a] [b]
instance Bifoldable BiList where
bifoldr f g z (BiList as bs) = foldr f (foldr g z bs) asA minimal Bifoldable definition consists of either bifoldMap or bifoldr. When defining more than this minimal set, one should ensure that the following identities hold:
bifold ≡ bifoldMap id id
bifoldMap f g ≡ bifoldr (mappend . f) (mappend . g) mempty
bifoldr f g z t ≡ appEndo (bifoldMap (Endo . f) (Endo . g) t) z
If the type is also an instance of Foldable, then it must satisfy (up to laziness):
bifoldl const ≡ foldl
bifoldr (flip const) ≡ foldr
bifoldMap (const mempty) ≡ foldMap
If the type is also a Bifunctor instance, it should satisfy:
bifoldMap f g ≡ bifold . bimap f g
which implies that
bifoldMap f g . bimap h i ≡ bifoldMap (f . h) (g . i)
Methods
bifold :: Monoid m => p m m -> mCombines the elements of a structure using a monoid.
bifold ≡ bifoldMap id idExamples
Basic usage:
Example1 expression bifold (Right [1, 2, 3])[1,2,3]
Example1 expression bifold (Left [5, 6])[5,6]
Example1 expression bifold ([1, 2, 3], [4, 5])[1,2,3,4,5]
Example1 expression bifold (Product 6, Product 7)Product {getProduct = 42}
Example1 expression bifold (Sum 6, Sum 7)Sum {getSum = 13}
bifoldMap :: Monoid m => (a -> m) -> (b -> m) -> p a b -> mCombines the elements of a structure, given ways of mapping them to a common monoid.
bifoldMap f g ≡ bifoldr (mappend . f) (mappend . g) memptyExamples
Basic usage:
Example1 expression bifoldMap (take 3) (fmap digitToInt) ([1..], "89")[1,2,3,8,9]
Example1 expression bifoldMap (take 3) (fmap digitToInt) (Left [1..])[1,2,3]
Example1 expression bifoldMap (take 3) (fmap digitToInt) (Right "89")[8,9]
bifoldr :: (a -> c -> c) -> (b -> c -> c) -> c -> p a b -> cCombines the elements of a structure in a right associative manner. Given a hypothetical function
toEitherList :: p a b -> [Either a b]yielding a list of all elements of a structure in order, the following would hold:bifoldr f g z ≡ foldr (either f g) z . toEitherListExamples
Basic usage:
> bifoldr (+) (*) 3 (5, 7) 26 -- 5 + (7 * 3) > bifoldr (+) (*) 3 (7, 5) 22 -- 7 + (5 * 3) > bifoldr (+) (*) 3 (Right 5) 15 -- 5 * 3 > bifoldr (+) (*) 3 (Left 5) 8 -- 5 + 3bifoldl :: (c -> a -> c) -> (c -> b -> c) -> c -> p a b -> cCombines the elements of a structure in a left associative manner. Given a hypothetical function
toEitherList :: p a b -> [Either a b]yielding a list of all elements of a structure in order, the following would hold:bifoldl f g z ≡ foldl (acc -> either (f acc) (g acc)) z . toEitherListNote that if you want an efficient left-fold, you probably want to use bifoldl' instead of bifoldl. The reason is that the latter does not force the "inner" results, resulting in a thunk chain which then must be evaluated from the outside-in.
Examples
Basic usage:
> bifoldl (+) (*) 3 (5, 7) 56 -- (5 + 3) * 7 > bifoldl (+) (*) 3 (7, 5) 50 -- (7 + 3) * 5 > bifoldl (+) (*) 3 (Right 5) 15 -- 5 * 3 > bifoldl (+) (*) 3 (Left 5) 8 -- 5 + 3
Instances11Bifoldable, …
Bifoldable ArgDefined in base-4.20.2.0 · Data.SemigroupBifoldable EitherDefined in base-4.20.2.0 · Data.BifoldableBifoldable Tuple2Defined in base-4.20.2.0 · Data.BifoldableClass laws for tuples hold only up to laziness. The Bifoldable methods are lazier than their Foldable counterparts. For example the law
bifoldr (flip const) ≡ foldrdoes not hold for tuples if laziness is exploited:Example2 expressions bifoldr (flip const) (:) [] (undefined :: (Int, Word)) `seq` ()()foldr (:) [] (undefined :: (Int, Word)) `seq` ()*** Exception: Prelude.undefined
Bifoldable ConstDefined in base-4.20.2.0 · Data.BifoldableBifoldable ConstantDefined in transformers-0.6.1.1 · Data.Functor.ConstantBifoldable (Tuple3 x)Defined in base-4.20.2.0 · Data.BifoldableBifoldable (K1 i)Defined in base-4.20.2.0 · Data.BifoldableBifoldable (Tuple4 x y)Defined in base-4.20.2.0 · Data.BifoldableBifoldable (Tuple5 x y z)Defined in base-4.20.2.0 · Data.BifoldableBifoldable (Tuple6 x y z w)Defined in base-4.20.2.0 · Data.BifoldableBifoldable (Tuple7 x y z w v)Defined in base-4.20.2.0 · Data.Bifoldable