packages feed

syntactic-2.0: benchmarks/JoiningTypes.hs

{-# LANGUAGE TemplateHaskell #-}

module JoiningTypes (main) where

import Criterion.Main
import Criterion.Config
import Data.Monoid
import Data.Syntactic
import Data.Syntactic.Functional

-- Normal DSL, not joined types.
data Expr1 t where
  EI    :: Int  -> Expr1 (Full Int)
  EB    :: Bool -> Expr1 (Full Bool)
  EAdd  :: Expr1 (Int :-> Int :-> Full Int)
  EEq   :: (Eq t) => Expr1 (t   :-> t   :-> Full Bool)
  EIf   :: Expr1 (Bool :-> a :-> a :-> Full a)

type Expr1' a = AST Expr1 (Full a)

int  :: Int -> Expr1' Int
int = Sym . EI

bool :: Bool -> Expr1' Bool
bool = Sym . EB

add  :: Expr1' Int -> Expr1' Int -> Expr1' Int
add a b = Sym EAdd :$ a :$ b

eq   :: (Eq a) => Expr1' a -> Expr1' a -> Expr1' Bool
eq a b = Sym EEq :$ a :$ b

if'  :: Expr1' Bool -> Expr1' a -> Expr1' a -> Expr1' a
if' c a b = Sym EIf :$ c :$ a :$ b

instance Render Expr1 where
  renderSym (EI n)  = "EI"
  renderSym (EB b)  = "EB"
  renderSym (EAdd)  = "EAdd"
  renderSym (EEq)   = "EEq"
  renderSym (EIf)   = "EIf"

interpretationInstances ''Expr1

instance Eval Expr1 where
  evalSym (EI n)  = n
  evalSym (EB b)  = b
  evalSym EAdd    = (+)
  evalSym EEq     = (==)
  evalSym EIf     = \c a b -> if c then a else b

instance EvalEnv Expr1 env where
  compileSym p (EI n) = compileSymDefault p (EI n)
  compileSym p (EB b) = compileSymDefault p (EB b)
  compileSym p EAdd   = compileSymDefault p EAdd
  compileSym p EEq    = compileSymDefault p EEq
  compileSym p EIf    = compileSymDefault p EIf

-- Joined types
data ExprI t where
  EIJ    :: Int  -> ExprI (Full Int)
  EAddJ  :: ExprI (Int :-> Int :-> Full Int)

data ExprB t where
  EBJ    :: Bool -> ExprB (Full Bool)
  EEqJ   :: (Eq t) => ExprB (t   :-> t   :-> Full Bool)
  EIfJ   :: ExprB (Bool :-> a :-> a :-> Full a)

type ExprJ = ExprI :+: ExprB
type ExprJ' a = AST ExprJ (Full a)

intJ  :: Int -> ExprJ' Int
intJ = Sym . inj . EIJ

boolJ :: Bool -> ExprJ' Bool
boolJ = Sym . inj . EBJ

addJ  :: ExprJ' Int -> ExprJ' Int -> ExprJ' Int
addJ a b = Sym (inj EAddJ) :$ a :$ b

eqJ   :: (Eq a) => ExprJ' a -> ExprJ' a -> ExprJ' Bool
eqJ a b = Sym (inj EEqJ) :$ a :$ b

ifJ  :: ExprJ' Bool -> ExprJ' a -> ExprJ' a -> ExprJ' a
ifJ c a b = Sym (inj EIfJ) :$ c :$ a :$ b

instance Render ExprI where
  renderSym (EIJ n)  = "EI"
  renderSym (EAddJ)  = "EAdd"
instance Render ExprB where
  renderSym (EBJ b)  = "EB"
  renderSym (EEqJ)   = "EEq"
  renderSym (EIfJ)   = "EIf"

interpretationInstances ''ExprI
interpretationInstances ''ExprB

instance Eval ExprI where
  evalSym (EIJ n) = n
  evalSym EAddJ   = (+)

instance Eval ExprB where
  evalSym (EBJ b) = b
  evalSym EEqJ    = (==)
  evalSym EIfJ    = \c a b -> if c then a else b

instance EvalEnv ExprI env where
  compileSym p (EIJ n) = compileSymDefault p (EIJ n)
  compileSym p EAddJ   = compileSymDefault p EAddJ

instance EvalEnv ExprB env where
  compileSym p (EBJ b) = compileSymDefault p (EBJ b)
  compileSym p EEqJ    = compileSymDefault p EEqJ
  compileSym p EIfJ    = compileSymDefault p EIfJ

-- Joined types (4 joins)

data Expr4J1 t where
  E4JI    :: Int  -> Expr4J1 (Full Int)
data Expr4J2 t where
  E4JB    :: Bool -> Expr4J2 (Full Bool)
data Expr4J3 t where
  E4JAdd  :: Expr4J3 (Int :-> Int :-> Full Int)
data Expr4J4 t where
  E4JEq   :: (Eq t) => Expr4J4 (t   :-> t   :-> Full Bool)
data Expr4J5 t where
  E4JIf   :: Expr4J5 (Bool :-> a :-> a :-> Full a)

type Expr4J = Expr4J1 :+: Expr4J2 :+: Expr4J3 :+: Expr4J4 :+: Expr4J5
type Expr4J' a = AST Expr4J (Full a)

int4  :: Int -> Expr4J' Int
int4 = Sym . inj . E4JI

bool4 :: Bool -> Expr4J' Bool
bool4 = Sym . inj . E4JB

add4  :: Expr4J' Int -> Expr4J' Int -> Expr4J' Int
add4 a b = Sym (inj E4JAdd) :$ a :$ b

eq4   :: (Eq a) => Expr4J' a -> Expr4J' a -> Expr4J' Bool
eq4 a b = Sym (inj E4JEq) :$ a :$ b

if4  :: Expr4J' Bool -> Expr4J' a -> Expr4J' a -> Expr4J' a
if4 c a b = Sym (inj E4JIf) :$ c :$ a :$ b

instance Render Expr4J1 where
  renderSym (E4JI n)  = "EI"

instance Render Expr4J2 where
  renderSym (E4JB b)  = "EB"

instance Render Expr4J3 where
  renderSym (E4JAdd)  = "EAdd"

instance Render Expr4J4 where
  renderSym (E4JEq)   = "EEq"

instance Render Expr4J5 where
  renderSym (E4JIf)   = "EIf"

interpretationInstances ''Expr4J1
interpretationInstances ''Expr4J2
interpretationInstances ''Expr4J3
interpretationInstances ''Expr4J4
interpretationInstances ''Expr4J5

instance Eval Expr4J1 where
  evalSym (E4JI n)  = n

instance Eval Expr4J2 where
  evalSym (E4JB b)  = b

instance Eval Expr4J3 where
  evalSym E4JAdd    = (+)

instance Eval Expr4J4 where
  evalSym E4JEq     = (==)

instance Eval Expr4J5 where
  evalSym E4JIf     = \c a b -> if c then a else b

instance EvalEnv Expr4J1 env where
  compileSym p (E4JI n)  = compileSymDefault p (E4JI n)

instance EvalEnv Expr4J2 env where
  compileSym p (E4JB b)  = compileSymDefault p (E4JB b)

instance EvalEnv Expr4J3 env where
  compileSym p E4JAdd    = compileSymDefault p E4JAdd

instance EvalEnv Expr4J4 env where
  compileSym p E4JEq     = compileSymDefault p E4JEq

instance EvalEnv Expr4J5 env where
  compileSym p E4JIf     = compileSymDefault p E4JIf

-- Expressions
syntacticExpr :: Int -> Expr1' Int
syntacticExpr 0 = if' (eq (int 5) (int 4)) (int 5) (int 0)
syntacticExpr n = (add (syntacticExpr (n-1)) (syntacticExpr (n-1)))

syntacticExprJ :: Int -> ExprJ' Int
syntacticExprJ 0 = ifJ (eqJ (intJ 5) (intJ 4)) (intJ 5) (intJ 0)
syntacticExprJ n = (addJ (syntacticExprJ (n-1)) (syntacticExprJ (n-1)))

syntacticExpr4J :: Int -> Expr4J' Int
syntacticExpr4J 0 = if4 (eq4 (int4 5) (int4 4)) (int4 5) (int4 0)
syntacticExpr4J n = (add4 (syntacticExpr4J (n-1)) (syntacticExpr4J (n-1)))

main :: IO ()
main = defaultMainWith (defaultConfig {cfgSummaryFile = Last $ Just "bench-results/joiningTypes.csv"}) (return ())
         [ bgroup "eval 10" [ bench "syntactic 0 joins" $ nf evalDen (syntacticExpr 10)
                            , bench "syntactic 1 join"  $ nf evalDen (syntacticExprJ 10)
                            , bench "syntactic 4 joins" $ nf evalDen (syntacticExpr4J 10)]
         , bgroup "eval 15" [ bench "syntactic 0 joins" $ nf evalDen (syntacticExpr 15)
                            , bench "syntactic 1 join"  $ nf evalDen (syntacticExprJ 15)
                            , bench "syntactic 4 joins" $ nf evalDen (syntacticExpr4J 15)]
         , bgroup "eval 20" [ bench "syntactic 0 joins" $ nf evalDen (syntacticExpr 20)
                            , bench "syntactic 1 join"  $ nf evalDen (syntacticExprJ 20)
                            , bench "syntactic 4 joins" $ nf evalDen (syntacticExpr4J 20)]
         , bgroup "size 10" [ bench "syntactic 0 joins" $ nf size (syntacticExpr 10)
                            , bench "syntactic 1 join"  $ nf size (syntacticExprJ 10)
                            , bench "syntactic 4 joins" $ nf evalDen (syntacticExpr4J 10)]
         , bgroup "size 15" [ bench "syntactic 0 joins" $ nf size (syntacticExpr 15)
                            , bench "syntactic 1 join"  $ nf size (syntacticExprJ 15)
                            , bench "syntactic 4 joins" $ nf evalDen (syntacticExpr4J 15)]
         , bgroup "size 20" [ bench "syntactic 0 joins" $ nf size (syntacticExpr 20)
                            , bench "syntactic 1 join"  $ nf size (syntacticExprJ 20)
                            , bench "syntactic 4 joins" $ nf evalDen (syntacticExpr4J 20)]]