module Main (main) where
import qualified Data.Generic.Enum as E
import Data.Stream.Typed (RunTimeStream)
import Data.Semigroup (Semigroup((<>)))
import Data.Bits ((.&.))
import Data.Foldable (foldl')
import Criterion
n :: Int
n = 10000000
f :: Int -> Int
f x = x*(x .&. 3)
g :: Int -> Int
g x = x*(x .&. 7)
xs :: Int -> RunTimeStream Int
xs n = E.enumFromTo 1 n
xl :: Int -> [Int]
xl n = [1..n]
sumG :: (Functor t, Foldable t, Semigroup (t Int)) => t Int -> Int
sumG x = foldl' (+) 0 ((fmap f x) <> (fmap g x))
sumS n = sumG (xs n)
sumL n = sumG (xl n)
fast :: Int -> Int
fast n = go g (go f 0 1 n) 1 n where
go :: (Int -> Int) -> Int -> Int -> Int -> Int
go f = go' where
go' :: Int -> Int -> Int -> Int
go' acc s i = if i == 0 then acc else let next_acc = acc + f s in next_acc `seq` go' next_acc (s + 1) (i - 1)
main :: IO ()
main = do
putStrLn ("n = " ++ show n)
putStrLn $ "Hand coded strict loop (Result = " ++ show (fast n) ++ " ):"
benchmark (nf fast n)
putStrLn $ "Using lists (Result = " ++ show (sumL n) ++ " ):"
benchmark (nf sumL n)
putStrLn $ "Using streams (Result = " ++ show (sumS n) ++ " ):"
benchmark (nf sumS n)