@@ -0,0 +1,76 @@
1+{-# LANGUAGE DeriveFunctor, FlexibleContexts, FlexibleInstances, KindSignatures, MultiParamTypeClasses,
2+ TypeApplications, TypeOperators, UndecidableInstances #-}
3+
4+module HigherOrder (marks) where
5+
6+import Control.Effect
7+import Control.Monad
8+import Data.Coerce
9+import Gauge.Main
10+
11+data HTTP (m :: * -> *) k
12+ = Open String k
13+ | Close k
14+ | Post String (String -> k)
15+ | HGet (String -> k)
16+ deriving Functor
17+
18+instance HFunctor HTTP where
19+ hmap _ = coerce
20+
21+open' :: (Member HTTP sig, Carrier sig m) => String -> m ()
22+open' s = send (Open s (gen ()))
23+
24+close' :: (Member HTTP sig, Carrier sig m) => m ()
25+close' = send (Close (gen ()))
26+
27+post' :: (Member HTTP sig, Carrier sig m) => String -> m String
28+post' s = send (Post s gen)
29+
30+get' :: (Member HTTP sig, Carrier sig m) => m String
31+get' = send (HGet gen)
32+
33+newtype HTTPC m a = HTTPC { runHTTPC :: m a }
34+
35+instance (Carrier sig m) => Carrier (HTTP :+: sig) (HTTPC m) where
36+ gen = HTTPC . gen
37+ alg = algS \/ (HTTPC . alg . handlePure runHTTPC) where
38+ algS (Open _ k) = k
39+ algS (Close k) = k
40+ algS (Post s k) = k s
41+ algS (HGet k) = k ""
42+
43+runHTTP :: (Carrier sig m) => Eff (HTTPC m) a -> m a
44+runHTTP = runHTTPC . interpret
45+
46+oneGet :: Int -> (Int, Int)
47+oneGet n = run (runState n get)
48+
49+countDown :: Int -> (Int,Int)
50+countDown start = run (runState start go)
51+ where go = get >>= (\n -> if n <= 0 then pure n else put (n-1) >> go)
52+
53+countDownExc :: Int -> Either String (Int,Int)
54+countDownExc start = run $ runError (runState start go)
55+ where go = get >>= (\n -> if n <= (0 :: Int) then throwError "wat" else put (n-1) >> go)
56+
57+prog :: (Monad m, Member HTTP sig, Carrier sig m) => m ()
58+prog = open' "cats" >> get' >> post' "cats" >> close'
59+
60+p :: (Monad m, Member HTTP sig, Carrier sig m) => Int -> m ()
61+p count = open' "cats" >> replicateM_ count (get' >> post' "cats") >> close'
62+
63+marks :: Benchmark
64+marks = bgroup "higher-order-effects"
65+ [ bgroup "State"
66+ [ bench "get" $ whnf oneGet 0
67+ , bench "countdown" $ whnf countDown 100
68+ ]
69+ , bgroup "State + Error"
70+ [ bench "countdownExc" $ whnf countDownExc 10000
71+ ]
72+ , bgroup "HTTP DSL"
73+ [ bench "simple" $ whnf (run . runHTTP) prog
74+ , bench "replicated" $ whnf (run . runHTTP . p) 100000
75+ ]
76+ ]