{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-} #if MIN_VERSION_base(4,18,0) # define HAS_FOLDABLE1_CONTAINERS MIN_VERSION_containers(0,6,7) #else # define HAS_FOLDABLE1_CONTAINERS 1 #endif module Main (main) where import Prelude hiding (foldl1, head, last, maximum) import Control.DeepSeq (NFData (..)) import Criterion.Main import qualified Data.Foldable as F (Foldable) import Data.Foldable1 import Data.List.NonEmpty (NonEmpty (..)) import Data.Semigroup (Min (..)) #if HAS_FOLDABLE1_CONTAINERS import Data.Tree (Tree (..)) #endif input :: NonEmpty Int input = 1 :| take 10000000 [2 .. ] #if HAS_FOLDABLE1_CONTAINERS tree :: Tree Int tree = go 7 0 where go :: Int -> Int -> Tree Int go n x | n <= 0 = Node x [] | otherwise = Node x [ go (pred n) (x * 10 + x') | x' <- [0 .. 9] ] #endif main :: IO () main = defaultMain -- NonEmpty left folds [ env (return input) $ \ne -> bgroup "NonEmpty-vanilla" [ bench "foldMap1 Min" $ whnf (getMin . foldMap1 Min) ne , bench "foldMap1' Min" $ whnf (getMin . foldMap1' Min) ne , bench "foldl1' min" $ whnf (foldl1' min) ne , bench "foldl1 min" $ whnf (foldl1 min) ne , bench "foldlMap1' id min" $ whnf (foldlMap1' id min) ne , bench "foldlMap1 id min" $ whnf (foldlMap1 id min) ne ] , env (return $ NE1 input) $ \ne -> bgroup "NonEmpty-foldMap1" [ bench "foldMap1 Min" $ whnf (getMin . foldMap1 Min) ne , bench "foldMap1' Min" $ whnf (getMin . foldMap1' Min) ne , bench "foldl1' min" $ whnf (foldl1' min) ne , bench "foldl1 min" $ whnf (foldl1 min) ne , bench "foldlMap1' id min" $ whnf (foldlMap1' id min) ne , bench "foldlMap1 id min" $ whnf (foldlMap1 id min) ne ] , env (return $ NE3 input) $ \ne -> bgroup "NonEmpty-foldrMap1" [ bench "foldMap1 Min" $ whnf (getMin . foldMap1 Min) ne , bench "foldMap1' Min" $ whnf (getMin . foldMap1' Min) ne , bench "foldl1' min" $ whnf (foldl1' min) ne , bench "foldl1 min" $ whnf (foldl1 min) ne , bench "foldlMap1' id min" $ whnf (foldlMap1' id min) ne , bench "foldlMap1 id min" $ whnf (foldlMap1 id min) ne ] #if HAS_FOLDABLE1_CONTAINERS -- Trees , env (return tree) $ \tr -> bgroup "Tree-vanilla" [ bench "head" $ whnf head tr , bench "last" $ whnf last tr , bench "maximum" $ whnf maximum tr , bench "maximum'" $ whnf (foldl1' max) tr , bench "foldMap1 Min" $ whnf (getMin . foldMap1 Min) tr , bench "foldMap1' Min" $ whnf (getMin . foldMap1' Min) tr , bench "foldl1' min" $ whnf (foldl1' min) tr , bench "foldl1 min" $ whnf (foldl1 min) tr , bench "foldlMap1' id min" $ whnf (foldlMap1' id min) tr , bench "foldlMap1 id min" $ whnf (foldlMap1 id min) tr ] , env (return $ Tree1 tree) $ \tr -> bgroup "Tree-foldMap1" [ bench "head" $ whnf head tr , bench "last" $ whnf last tr , bench "maximum" $ whnf maximum tr , bench "maximum'" $ whnf (foldl1' max) tr , bench "foldMap1 Min" $ whnf (getMin . foldMap1 Min) tr , bench "foldMap1' Min" $ whnf (getMin . foldMap1' Min) tr , bench "foldl1' min" $ whnf (foldl1' min) tr , bench "foldl1 min" $ whnf (foldl1 min) tr , bench "foldlMap1' id min" $ whnf (foldlMap1' id min) tr , bench "foldlMap1 id min" $ whnf (foldlMap1 id min) tr ] , env (return $ Tree3 tree) $ \tr -> bgroup "Tree-foldr1Map" [ bench "head" $ whnf head tr , bench "last" $ whnf last tr , bench "maximum" $ whnf maximum tr , bench "maximum'" $ whnf (foldl1' max) tr , bench "foldMap1 Min" $ whnf (getMin . foldMap1 Min) tr , bench "foldMap1' Min" $ whnf (getMin . foldMap1' Min) tr , bench "foldl1' min" $ whnf (foldl1' min) tr , bench "foldl1 min" $ whnf (foldl1 min) tr , bench "foldlMap1' id min" $ whnf (foldlMap1' id min) tr , bench "foldlMap1 id min" $ whnf (foldlMap1 id min) tr ] #endif ] ------------------------------------------------------------------------------- -- NonEmpty variants ------------------------------------------------------------------------------- -- Using foldMap1 only newtype NE1 a = NE1 (NonEmpty a) deriving (Functor, F.Foldable) instance NFData a => NFData (NE1 a) where rnf (NE1 xs) = rnf xs instance Foldable1 NE1 where foldMap1 f (NE1 xs) = foldMap1 f xs -- Using toNonEmpty -- newtype NE2 a = NE2 (NonEmpty a) -- deriving (Functor, F.Foldable) -- -- instance NFData a => NFData (NE2 a) where -- rnf (NE2 xs) = rnf xs -- -- instance Foldable1 NE2 where -- toNonEmpty (NE2 xs) = toNonEmpty xs -- Using to foldrMap1 newtype NE3 a = NE3 (NonEmpty a) deriving (Functor, F.Foldable) instance NFData a => NFData (NE3 a) where rnf (NE3 xs) = rnf xs instance Foldable1 NE3 where foldrMap1 g f (NE3 xs) = foldrMap1 g f xs #if HAS_FOLDABLE1_CONTAINERS ------------------------------------------------------------------------------- -- Tree variants ------------------------------------------------------------------------------- -- Using foldMap1 only newtype Tree1 a = Tree1 (Tree a) deriving (Functor, F.Foldable) instance NFData a => NFData (Tree1 a) where rnf (Tree1 xs) = rnf xs instance Foldable1 Tree1 where foldMap1 f (Tree1 xs) = foldMap1 f xs -- Using toNonEmpty -- newtype Tree2 a = Tree2 (Tree a) -- deriving (Functor, F.Foldable) -- -- instance NFData a => NFData (Tree2 a) where -- rnf (Tree2 xs) = rnf xs -- -- instance Foldable1 Tree2 where -- toNonEmpty (Tree2 xs) = toNonEmpty xs -- Using to foldrMap1 newtype Tree3 a = Tree3 (Tree a) deriving (Functor, F.Foldable) instance NFData a => NFData (Tree3 a) where rnf (Tree3 xs) = rnf xs instance Foldable1 Tree3 where foldrMap1 f g (Tree3 xs) = foldrMap1 f g xs #endif