packages feed

extensible-0.4.3: benchmarks/eff-comparison.hs

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DataKinds, TypeOperators #-}
{-# OPTIONS_GHC -ddump-simpl -dsuppress-all #-}
import Data.Void

-- extensible-effects
import qualified Control.Eff as ExtEff
import qualified Control.Eff.Reader.Strict as ExtEff
import qualified Control.Eff.Writer.Strict as ExtEff
import qualified Control.Eff.State.Strict as ExtEff

-- effin
import qualified Control.Effect as Effin
import qualified Control.Effect.Reader as Effin
import qualified Control.Effect.Writer as Effin
import qualified Control.Effect.State as Effin

-- freer
import qualified Control.Monad.Freer as Freer
import qualified Control.Monad.Freer.Reader as Freer
import qualified Control.Monad.Freer.Writer as Freer
import qualified Control.Monad.Freer.State as Freer

import Control.Monad.Reader
import Control.Monad.State.Strict
import Control.Monad.Writer.Strict
import Control.Monad.RWS.Strict

import Data.Extensible.Effect
import Data.Extensible.Effect.Default

import Criterion.Main

testExtEff :: (ExtEff.Member (ExtEff.Reader Int) r
  , ExtEff.Member (ExtEff.State Int) r
  , ExtEff.Member (ExtEff.Writer (Sum Int)) r)
  => ExtEff.Eff r ()
testExtEff = replicateM_ 100 $ do
  r :: Int <- ExtEff.ask
  s <- ExtEff.get
  ExtEff.tell (Sum s)
  ExtEff.put $! s + r

runExtEff :: ExtEff.Eff
  ( ExtEff.Reader Int
  ExtEff.:> ExtEff.State Int
  ExtEff.:> ExtEff.Writer (Sum Int)
  ExtEff.:> Void) a -> (Sum Int, (Int, a))
runExtEff = ExtEff.run
  . ExtEff.runMonoidWriter
  . ExtEff.runState 0
  . flip ExtEff.runReader 1

testEffin :: (Effin.EffectReader Int l
  , Effin.EffectState Int l
  , Effin.EffectWriter (Sum Int) l)
  => Effin.Effect l ()
testEffin = replicateM_ 100 $ do
  r <- Effin.ask
  s <- Effin.get
  Effin.tell (Sum s)
  Effin.put $! s + r

runEffin = Effin.runEffect
  . Effin.runWriter
  . Effin.runState 0
  . Effin.runReader 1

testFreer :: (Freer.Member (Freer.Reader Int) r
  , Freer.Member (Freer.State Int) r
  , Freer.Member (Freer.Writer (Sum Int)) r)
  => Freer.Eff r ()
testFreer = replicateM_ 100 $ do
  r :: Int <- Freer.ask
  s <- Freer.get
  Freer.tell (Sum s)
  Freer.put $! s + r

runFreer :: Freer.Eff '[Freer.Reader Int, Freer.State Int, Freer.Writer (Sum Int)] a
  -> ((a, Int), Sum Int)
runFreer = Freer.run
  . Freer.runWriter
  . flip Freer.runState 0
  . flip Freer.runReader 1

testMTL :: (MonadReader Int m, MonadState Int m, MonadWriter (Sum Int) m)
  => m ()
testMTL = replicateM_ 100 $ do
  r <- ask
  s <- get
  tell (Sum s)
  put $! s + r

runMTL :: ReaderT Int (StateT Int (Writer (Sum Int))) a -> ((a, Int), Sum Int)
runMTL = runWriter
  . flip runStateT 0
  . flip runReaderT 1

runExtensible :: Eff '[ReaderDef Int, StateDef Int, WriterDef (Sum Int)] a
  -> ((a, Int), Sum Int)
runExtensible = leaveEff
  . runWriterDef
  . flip runStateDef 0
  . flip runReaderDef 1

main = defaultMain
  [ bgroup "rws"
    [ bench "extensible" $ nf runExtensible testMTL
    , bench "mtl" $ nf runMTL testMTL
    , bench "mtl-RWS" $ nf (\m -> runRWS m 0 1) testMTL
    , bench "exteff" $ nf runExtEff testExtEff
    , bench "effin" $ nf runEffin testEffin
    , bench "freer-effects" $ nf runFreer testFreer
    ]
  ]