packages feed

packed-data-0.1.0.0: benchmark/ast/Main.hs

{-# LANGUAGE BangPatterns #-}

module Main (main) where

import Criterion.Main (bench, defaultMain, nf, nfAppIO)
import Data.Packed
import qualified Data.Packed.Reader as R

data Arithmetic where
    Val :: Double -> Arithmetic
    Add :: Arithmetic -> Arithmetic -> Arithmetic
    Sub :: Arithmetic -> Arithmetic -> Arithmetic
    Mul :: Arithmetic -> Arithmetic -> Arithmetic
    Div :: Arithmetic -> Arithmetic -> Arithmetic

$(mkPacked ''Arithmetic [])

eval :: Arithmetic -> Double
eval (Val d) = d
eval (Add a b) = (eval a) + eval b
eval (Sub a b) = eval a - eval b
eval (Mul a b) = eval a * eval b
eval (Div a b) = eval a / eval b

evalPacked :: PackedReader '[Arithmetic] r Double
evalPacked =
    caseArithmetic
        reader
        (fn (+))
        (fn (-))
        (fn (*))
        (fn (/))
  where
    {-# INLINE fn #-}
    fn op = R.do
        !l <- evalPacked
        !r <- evalPacked
        R.return (l `op` r)

main :: IO ()
main = do
    let bigAst = genBigAst
        packedAst = pack bigAst
    defaultMain
        [ bench "packed" $ nfAppIO (runReader evalPacked) packedAst
        , bench "unpacked" $ nf eval bigAst
        ]

genBigAst :: Arithmetic
genBigAst = go 27
  where
    go :: Int -> Arithmetic
    go 0 = Val 3
    go n
        | n `mod` 5 == 0 = Div child child
        | n `mod` 4 == 0 = Mul child child
        | n `mod` 3 == 0 = Sub child child
        | otherwise = Add child child
      where
        child = go (n - 1)