{-# language DeriveGeneric #-}
{-# language TypeFamilies #-}
module Main where
import Criterion
import Criterion.Main
import Control.Newtype
import Data.Coerce
import Data.Semigroup
import GHC.Generics
newtype MySumDerive = MySumDerive Int
deriving (Generic)
instance Newtype MySumDerive
instance Semigroup MySumDerive where
MySumDerive x <> MySumDerive y = MySumDerive (x + y)
instance Monoid MySumDerive where
mappend = (<>)
mempty = MySumDerive 0
newtype MySumManual = MySumManual Int
instance Newtype MySumManual where
type O MySumManual = Int
pack = MySumManual
unpack (MySumManual x) = x
instance Semigroup MySumManual where
MySumManual x <> MySumManual y = MySumManual (x + y)
instance Monoid MySumManual where
mappend = (<>)
mempty = MySumManual 0
mySumDerive :: [Int] -> Int
mySumDerive xs = ala MySumDerive foldMap xs
mySumManual :: [Int] -> Int
mySumManual xs = ala MySumManual foldMap xs
mySumOldschool :: [Int] -> Int
mySumOldschool xs = s
where MySumDerive s = foldMap MySumDerive xs
mySumCoerce :: [Int] -> Int
mySumCoerce xs = coerce (foldMap coerce xs :: MySumDerive)
mySumCoerce' :: [Int] -> Int
mySumCoerce' xs = coerce (mconcat (coerce xs) :: MySumDerive)
preludeSum :: [Int] -> Int
preludeSum xs = sum xs
main :: IO ()
main = defaultMain [
env (return [1..5 :: Int]) $ \ns ->
let bench' s f = bench s (whnf f ns)
in bgroup "[1..5 :: Int]"
[ bgroup "foldMap"
[ bench' "ala MySumDerive" mySumDerive
, bench' "ala MySumManual" mySumManual
, bench' "manual wrap & unwrap" mySumOldschool
, bench' "coerce" mySumCoerce
]
, bench' "coerce . mconcat . coerce" mySumCoerce'
, bench' "Prelude.sum" preludeSum
]
]