{-# 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.
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) zIf 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) ≡ foldMapIf the type is also a Bifunctor instance, it should satisfy:
bifoldMap f g ≡ bifold . bimap f gwhich implies that
bifoldMap f g . bimap h i ≡ bifoldMap (f . h) (g . i)