on master help sign in
Merge pull request #605 from Lysxia/benchmark-single-aeson

Add flag for benchmarks to select local or external aeson dependency

commitecc0663538910edd44b0d91f81b3810e1e599d09 authorAdam Bergmark <adam@bergmark.nl> dateMon 20 Nov 2017, 18:23 (9 years ago) parenta17a0e85dcebb3
16 files changed+220−524
benchmarks/AesonFoldable.hs+13−41 benchmarks/AesonMap.hs+38−55 benchmarks/AesonParse.hs+1−2 benchmarks/Compare.hs+1−2 benchmarks/CompareWithJSON.hs+20−31 benchmarks/Escape.hs+3−3 benchmarks/Micro.hs+6−5 benchmarks/Typed/Common.hs−10 benchmarks/Typed/Generic.hs+13−30 benchmarks/Typed/Manual.hs+13−30 benchmarks/Typed/TH.hs+13−30 benchmarks/aeson-benchmarks.cabal+99−76 examples/Twitter/Generic.hs−36 examples/Twitter/Manual.hs−135 examples/Twitter/Options.hs−21 examples/Twitter/TH.hs−17
benchmarks/AesonFoldable.hs+13−41
@@ -1,5 +1,4 @@
11{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE PackageImports #-}
32
43module Main (main) where
54
@@ -9,8 +8,7 @@ import Prelude ()
98import Prelude.Compat
109
1110import Data.Foldable (toList)
12−import qualified "aeson" Data.Aeson as A
13−import qualified "aeson-benchmarks" Data.Aeson as B
11+import qualified Data.Aeson as A
1412import qualified Data.Sequence as S
1513import qualified Data.Vector as V
1614import qualified Data.Vector.Unboxed as U
@@ -21,10 +19,6 @@ import qualified Data.Vector.Unboxed as U
2119
2220newtype L f = L { getL :: f Int }
2321
24−instance Foldable f => B.ToJSON (L f) where
25− toJSON = error "do not use this"
26− toEncoding = B.toEncoding . toList . getL
27−
2822instance Foldable f => A.ToJSON (L f) where
2923 toJSON = error "do not use this"
3024 toEncoding = A.toEncoding . toList . getL
@@ -35,10 +29,6 @@ instance Foldable f => A.ToJSON (L f) where
3529
3630newtype F f = F { getF :: f Int }
3731
38−instance Foldable f => B.ToJSON (F f) where
39− toJSON = error "do not use this"
40− toEncoding = B.foldable . getF
41−
4232instance Foldable f => A.ToJSON (F f) where
4333 toJSON = error "do not use this"
4434 toEncoding = A.foldable . getF
@@ -63,52 +53,34 @@ valueUVector = U.fromList valueList
6353-- Main
6454-------------------------------------------------------------------------------
6555
66−benchEncodeA
56+benchEncode
6757 :: A.ToJSON a
6858 => String
6959 -> a
7060 -> Benchmark
71−benchEncodeA name val
61+benchEncode name val
7262 = bench ("A " ++ name) $ nf A.encode val
7363
74−benchEncodeB
75− :: B.ToJSON a
76− => String
77− -> a
78− -> Benchmark
79−benchEncodeB name val
80− = bench ("B " ++ name) $ nf B.encode val
81−
8264main :: IO ()
8365main = defaultMain
8466 [ bgroup "encode"
8567 [ bgroup "List"
86− [ benchEncodeB "-" valueList
87− , benchEncodeB "L" $ L valueList
88− , benchEncodeB "F" $ F valueList
89− , benchEncodeA "-" valueList
90− , benchEncodeA "L" $ L valueList
91− , benchEncodeA "F" $ F valueList
68+ [ benchEncode "-" valueList
69+ , benchEncode "L" $ L valueList
70+ , benchEncode "F" $ F valueList
9271 ]
9372 , bgroup "Seq"
94− [ benchEncodeB "-" valueSeq
95− , benchEncodeB "L" $ L valueSeq
96− , benchEncodeB "F" $ F valueSeq
97− , benchEncodeA "-" valueSeq
98− , benchEncodeA "L" $ L valueSeq
99− , benchEncodeA "F" $ F valueSeq
73+ [ benchEncode "-" valueSeq
74+ , benchEncode "L" $ L valueSeq
75+ , benchEncode "F" $ F valueSeq
10076 ]
10177 , bgroup "Vector"
102− [ benchEncodeB "-" valueVector
103− , benchEncodeB "L" $ L valueVector
104− , benchEncodeB "F" $ F valueVector
105− , benchEncodeA "-" valueVector
106− , benchEncodeA "L" $ L valueVector
107− , benchEncodeA "F" $ F valueVector
78+ [ benchEncode "-" valueVector
79+ , benchEncode "L" $ L valueVector
80+ , benchEncode "F" $ F valueVector
10881 ]
10982 , bgroup "Vector.Unboxed"
110− [ benchEncodeB "-" valueUVector
111− , benchEncodeA "-" valueUVector
83+ [ benchEncode "-" valueUVector
11284 ]
11385 ]
11486 ]
benchmarks/AesonMap.hs+38−55
@@ -1,6 +1,4 @@
11{-# LANGUAGE FlexibleContexts #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE PackageImports #-}
42{-# LANGUAGE RankNTypes #-}
53
64{-# OPTIONS_GHC -fno-warn-orphans #-}
@@ -15,9 +13,8 @@ import Criterion.Main
1513import Data.Hashable
1614import Data.Proxy (Proxy (..))
1715import Data.Tagged (Tagged (..))
18−import qualified "aeson" Data.Aeson as A
19−import qualified "aeson-benchmarks" Data.Aeson as B
20−import qualified "aeson-benchmarks" Data.Aeson.Types as B (fromJSONKeyCoerce)
16+import Data.Aeson
17+import Data.Aeson.Types (fromJSONKeyCoerce)
2118import qualified Data.ByteString.Lazy as LBS
2219import qualified Data.HashMap.Strict as HM
2320import qualified Data.Map as M
@@ -47,10 +44,10 @@ instance NFData T1 where
4744instance Hashable T1 where
4845 hashWithSalt salt (T1 t) = hashWithSalt salt t
4946
50−instance B.FromJSON T1 where
51− parseJSON = B.withText "T1" $ pure . T1
52−instance B.FromJSONKey T1 where
53− fromJSONKey = B.FromJSONKeyText T1
47+instance FromJSON T1 where
48+ parseJSON = withText "T1" $ pure . T1
49+instance FromJSONKey T1 where
50+ fromJSONKey = FromJSONKeyText T1
5451
5552-------------------------------------------------------------------------------
5653-- Coerce
@@ -64,10 +61,10 @@ instance NFData T2 where
6461instance Hashable T2 where
6562 hashWithSalt salt (T2 t) = hashWithSalt salt t
6663
67−instance B.FromJSON T2 where
68− parseJSON = B.withText "T2" $ pure . T2
69−instance B.FromJSONKey T2 where
70− fromJSONKey = B.fromJSONKeyCoerce
64+instance FromJSON T2 where
65+ parseJSON = withText "T2" $ pure . T2
66+instance FromJSONKey T2 where
67+ fromJSONKey = fromJSONKeyCoerce
7168
7269-------------------------------------------------------------------------------
7370-- TextParser
@@ -81,10 +78,10 @@ instance NFData T3 where
8178instance Hashable T3 where
8279 hashWithSalt salt (T3 t) = hashWithSalt salt t
8380
84−instance B.FromJSON T3 where
85− parseJSON = B.withText "T3" $ pure . T3
86−instance B.FromJSONKey T3 where
87− fromJSONKey = B.FromJSONKeyTextParser (pure . T3)
81+instance FromJSON T3 where
82+ parseJSON = withText "T3" $ pure . T3
83+instance FromJSONKey T3 where
84+ fromJSONKey = FromJSONKeyTextParser (pure . T3)
8885
8986-------------------------------------------------------------------------------
9087-- Values
@@ -97,40 +94,30 @@ value1000 = value 1000
9794value10000 = value 10000
9895
9996encodedValue10 :: LBS.ByteString
100−encodedValue10 = B.encode value10
97+encodedValue10 = encode value10
10198
10299encodedValue100 :: LBS.ByteString
103−encodedValue100 = B.encode value100
100+encodedValue100 = encode value100
104101
105102encodedValue1000 :: LBS.ByteString
106−encodedValue1000 = B.encode value1000
103+encodedValue1000 = encode value1000
107104
108105encodedValue10000 :: LBS.ByteString
109−encodedValue10000 = B.encode value10000
106+encodedValue10000 = encode value10000
110107
111108-------------------------------------------------------------------------------
112109-- Helpers
113110-------------------------------------------------------------------------------
114111
115−decodeHMB
116− :: (B.FromJSONKey k, Eq k, Hashable k)
112+decodeHM
113+ :: (FromJSON (HM.HashMap k T.Text), Eq k, Hashable k)
117114 => Proxy k -> LBS.ByteString -> Maybe (HM.HashMap k T.Text)
118−decodeHMB _ = B.decode
115+decodeHM _ = decode
119116
120−decodeHMA
121− :: (A.FromJSON (HM.HashMap k T.Text), Eq k, Hashable k)
122− => Proxy k -> LBS.ByteString -> Maybe (HM.HashMap k T.Text)
123−decodeHMA _ = A.decode
124−
125−decodeMapB
126− :: (B.FromJSONKey k, Ord k)
127− => Proxy k -> LBS.ByteString -> Maybe (M.Map k T.Text)
128−decodeMapB _ = B.decode
129−
130−decodeMapA
131− :: (A.FromJSON (M.Map k T.Text), Ord k)
117+decodeMap
118+ :: (FromJSON (M.Map k T.Text), Ord k)
132119 => Proxy k -> LBS.ByteString -> Maybe (M.Map k T.Text)
133−decodeMapA _ = A.decode
120+decodeMap _ = decode
134121
135122proxyText :: Proxy T.Text
136123proxyText = Proxy
@@ -156,15 +143,14 @@ benchDecodeHM
156143 -> LBS.ByteString
157144 -> Benchmark
158145benchDecodeHM name val = bgroup name
159− [ bench "Text" $ nf (decodeHMB proxyText) val
160− , bench "Identity" $ nf (decodeHMB proxyT1) val
161− , bench "Coerce" $ nf (decodeHMB proxyT2) val
162− , bench "Parser" $ nf (decodeHMB proxyT3) val
163− , bench "aeson-hackage" $ nf (decodeHMA proxyText) val
164− , bench "Tagged Text" $ nf (decodeHMB $ proxyTagged proxyText) val
165− , bench "Tagged Identity" $ nf (decodeHMB $ proxyTagged proxyT1) val
166− , bench "Tagged Coerce" $ nf (decodeHMB $ proxyTagged proxyT2) val
167− , bench "Tagged Parser" $ nf (decodeHMB $ proxyTagged proxyT3) val
146+ [ bench "Text" $ nf (decodeHM proxyText) val
147+ , bench "Identity" $ nf (decodeHM proxyT1) val
148+ , bench "Coerce" $ nf (decodeHM proxyT2) val
149+ , bench "Parser" $ nf (decodeHM proxyT3) val
150+ , bench "Tagged Text" $ nf (decodeHM $ proxyTagged proxyText) val
151+ , bench "Tagged Identity" $ nf (decodeHM $ proxyTagged proxyT1) val
152+ , bench "Tagged Coerce" $ nf (decodeHM $ proxyTagged proxyT2) val
153+ , bench "Tagged Parser" $ nf (decodeHM $ proxyTagged proxyT3) val
168154 ]
169155
170156benchDecodeMap
@@ -172,11 +158,10 @@ benchDecodeMap
172158 -> LBS.ByteString
173159 -> Benchmark
174160benchDecodeMap name val = bgroup name
175− [ bench "Text" $ nf (decodeMapB proxyText) val
176− , bench "Identity" $ nf (decodeMapB proxyT1) val
177− , bench "Coerce" $ nf (decodeMapB proxyT2) val
178− , bench "Parser" $ nf (decodeMapB proxyT3) val
179− , bench "aeson-hackage" $ nf (decodeMapA proxyText) val
161+ [ bench "Text" $ nf (decodeMap proxyText) val
162+ , bench "Identity" $ nf (decodeMap proxyT1) val
163+ , bench "Coerce" $ nf (decodeMap proxyT2) val
164+ , bench "Parser" $ nf (decodeMap proxyT3) val
180165 ]
181166
182167benchEncodeHM
@@ -184,8 +169,7 @@ benchEncodeHM
184169 -> HM.HashMap T.Text T.Text
185170 -> Benchmark
186171benchEncodeHM name val = bgroup name
187− [ bench "Text" $ nf B.encode val
188− , bench "aeson-0.11" $ nf A.encode val
172+ [ bench "Text" $ nf encode val
189173 ]
190174
191175benchEncodeMap
@@ -193,8 +177,7 @@ benchEncodeMap
193177 -> HM.HashMap T.Text T.Text
194178 -> Benchmark
195179benchEncodeMap name val = bgroup name
196− [ bench "Text" $ nf B.encode val'
197− , bench "aeson-0.11" $ nf A.encode val'
180+ [ bench "Text" $ nf encode val'
198181 ]
199182 where
200183 val' :: M.Map T.Text T.Text
benchmarks/AesonParse.hs+1−2
@@ -1,13 +1,12 @@
11{-# LANGUAGE BangPatterns #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE PackageImports #-}
43
54module Main (main) where
65
76import Prelude ()
87import Prelude.Compat
98
10−import "aeson-benchmarks" Data.Aeson
9+import Data.Aeson
1110import Control.Monad
1211import Data.Attoparsec.ByteString (IResult(..), parseWith)
1312import Data.Time.Clock
benchmarks/Compare.hs+1−2
@@ -1,4 +1,3 @@
1−{-# LANGUAGE PackageImports #-}
21{-# LANGUAGE ScopedTypeVariables #-}
32
43module Main (main) where
@@ -14,7 +13,7 @@ import Data.Json.Builder
1413import Twitter
1514import Twitter.Manual ()
1615import Typed.Common
17−import qualified "aeson-benchmarks" Data.Aeson as Aeson
16+import qualified Data.Aeson as Aeson
1817import qualified Compare.JsonBench as JsonBench
1918
2019main :: IO ()
benchmarks/CompareWithJSON.hs+20−31
@@ -1,4 +1,3 @@
1−{-# LANGUAGE PackageImports #-}
21{-# OPTIONS_GHC -fno-warn-orphans #-}
32
43module Main (main) where
@@ -11,10 +10,9 @@ import Blaze.ByteString.Builder.Char.Utf8 (fromString)
1110import Control.DeepSeq (NFData(rnf))
1211import Criterion.Main
1312import Data.Maybe (fromMaybe)
14−import qualified "aeson-benchmarks" Data.Aeson as A
15−import qualified "aeson-benchmarks" Data.Aeson.Text as A
16−import qualified "aeson-benchmarks" Data.Aeson.Parser.Internal as I
17−import qualified "aeson" Data.Aeson as B
13+import qualified Data.Aeson as A
14+import qualified Data.Aeson.Text as A
15+import qualified Data.Aeson.Parser.Internal as I
1816import qualified Data.ByteString as BS
1917import qualified Data.ByteString.Lazy as BL
2018import qualified Data.Text.Lazy as TL
@@ -39,20 +37,14 @@ decodeJ s =
3937 J.Ok v -> v
4038 J.Error _ -> error "fail to parse via JSON"
4139
42−decodeA :: BL.ByteString -> A.Value
43−decodeA s = fromMaybe (error "fail to parse via Aeson") $ A.decode s
40+decode :: BL.ByteString -> A.Value
41+decode s = fromMaybe (error "fail to parse via Aeson") $ A.decode s
4442
45−decodeA' :: BL.ByteString -> A.Value
46−decodeA' s = fromMaybe (error "fail to parse via Aeson") $ A.decode' s
43+decode' :: BL.ByteString -> A.Value
44+decode' s = fromMaybe (error "fail to parse via Aeson") $ A.decode' s
4745
48−decodeAS :: BS.ByteString -> A.Value
49−decodeAS s = fromMaybe (error "fail to parse via Aeson") $ A.decodeStrict' s
50−
51−decodeB :: BL.ByteString -> B.Value
52−decodeB s = fromMaybe (error "fail to parse via Aeson") $ B.decode s
53−
54−decodeBS :: BS.ByteString -> B.Value
55−decodeBS s = fromMaybe (error "fail to parse via Aeson") $ B.decodeStrict' s
46+decodeS :: BS.ByteString -> A.Value
47+decodeS s = fromMaybe (error "fail to parse via Aeson") $ A.decodeStrict' s
5648
5749decodeIP :: BL.ByteString -> A.Value
5850decodeIP s = fromMaybe (error "fail to parse via Parser.decodeWith") $
@@ -80,32 +72,29 @@ main = do
8072 defaultMain [
8173 bgroup "decode" [
8274 bgroup "en" [
83− bench "aeson/lazy" $ nf decodeA enA
84− , bench "aeson/strict" $ nf decodeA' enA
85− , bench "aeson/stricter" $ nf decodeAS enS
86− , bench "aeson/hackage" $ nf decodeB enA
87− , bench "aeson/hackage'" $ nf decodeBS enS
75+ bench "aeson/lazy" $ nf decode enA
76+ , bench "aeson/strict" $ nf decode' enA
77+ , bench "aeson/stricter" $ nf decodeS enS
8878 , bench "aeson/parser" $ nf decodeIP enA
8979 , bench "json" $ nf decodeJ enJ
9080 ]
9181 , bgroup "jp" [
92− bench "aeson" $ nf decodeA jpA
93− , bench "aeson/stricter" $ nf decodeAS jpS
94− , bench "aeson/hackage" $ nf decodeB jpA
82+ bench "aeson" $ nf decode jpA
83+ , bench "aeson/stricter" $ nf decodeS jpS
9584 , bench "json" $ nf decodeJ jpJ
9685 ]
9786 ]
9887 , bgroup "encode" [
9988 bgroup "en" [
100− bench "aeson-to-bytestring" $ nf A.encode (decodeA enA)
101− , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decodeA enA)
102− , bench "aeson-to-text" $ nf encodeToText (decodeA enA)
89+ bench "aeson-to-bytestring" $ nf A.encode (decode enA)
90+ , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decode enA)
91+ , bench "aeson-to-text" $ nf encodeToText (decode enA)
10392 , bench "json" $ nf encodeJ (decodeJ enJ)
10493 ]
10594 , bgroup "jp" [
106− bench "aeson-to-bytestring" $ nf A.encode (decodeA jpA)
107− , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decodeA jpA)
108− , bench "aeson-to-text" $ nf encodeToText (decodeA jpA)
95+ bench "aeson-to-bytestring" $ nf A.encode (decode jpA)
96+ , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decode jpA)
97+ , bench "aeson-to-text" $ nf encodeToText (decode jpA)
10998 , bench "json" $ nf encodeJ (decodeJ jpJ)
11099 ]
111100 ]
benchmarks/Escape.hs+3−3
@@ -1,5 +1,5 @@
1−{-# LANGUAGE PackageImports #-}
21{-# LANGUAGE ScopedTypeVariables #-}
2+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
33
44module Main (main) where
55
@@ -7,8 +7,8 @@ import Prelude ()
77import Prelude.Compat
88
99import Criterion.Main
10−import qualified "aeson-benchmarks" Data.Aeson.Parser.UnescapeFFI as FFI
11−import qualified "aeson-benchmarks" Data.Aeson.Parser.UnescapePure as Pure
10+import qualified Data.Aeson.Parser.UnescapeFFI as FFI
11+import qualified Data.Aeson.Parser.UnescapePure as Pure
1212
1313import qualified Data.ByteString.Char8 as BS
1414import System.Environment (getArgs, withArgs)
benchmarks/Micro.hs+6−5
@@ -4,8 +4,9 @@ import Prelude ()
44import Prelude.Compat
55
66import Criterion.Main
7−import qualified Data.Aeson.Encoding.Builder as AB
8−import qualified Data.ByteString.Builder as B
7+
8+-- Encoding is a newtype wrapper around Builder
9+import Data.Aeson.Encoding (text, string, encodingToLazyByteString)
910import qualified Data.Text as T
1011
1112main :: IO ()
@@ -13,8 +14,8 @@ main = do
1314 let txt = "append (append b (primBounded w1 x1)) (primBounded w2 x2)"
1415 defaultMain [
1516 bgroup "string" [
16− bench "text" $ nf (B.toLazyByteString . AB.text) (T.pack txt)
17− , bench "string direct" $ nf (B.toLazyByteString . AB.string) txt
18− , bench "string via text" $ nf (B.toLazyByteString . AB.text . T.pack) txt
17+ bench "text" $ nf (encodingToLazyByteString . text) (T.pack txt)
18+ , bench "string direct" $ nf (encodingToLazyByteString . string) txt
19+ , bench "string via text" $ nf (encodingToLazyByteString . text . T.pack) txt
1920 ]
2021 ]
benchmarks/Typed/Common.hs−10
@@ -1,8 +1,3 @@
1−{-# LANGUAGE CPP #-}
2−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
3−{-# LANGUAGE PackageImports #-}
4−#endif
5−
61{-# OPTIONS_GHC -fno-warn-unused-imports #-}
72
83module Typed.Common (load) where
@@ -14,12 +9,7 @@ import Data.ByteString.Lazy as L
149import System.Exit
1510import System.IO
1611
17−#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
1812import Data.Aeson hiding (Result)
19−#else
20−import "aeson" Data.Aeson hiding (Result)
21−import qualified "aeson-benchmarks" Data.Aeson as B
22−#endif
2313
2414load :: FromJSON a => FilePath -> IO a
2515load fileName = do
benchmarks/Typed/Generic.hs+13−30
@@ -1,60 +1,43 @@
1−{-# LANGUAGE PackageImports #-}
21module Typed.Generic (benchmarks, decodeBenchmarks) where
32
43import Prelude ()
54import Prelude.Compat
65
7−import "aeson" Data.Aeson hiding (Result)
6+import Data.Aeson hiding (Result)
87import Criterion
98import Data.ByteString.Lazy as L
109import Twitter.Generic
1110import Typed.Common
12−import qualified "aeson-benchmarks" Data.Aeson as B
1311
14−encodeDirectA :: Result -> L.ByteString
15−encodeDirectA = encode
12+encodeDirect :: Result -> L.ByteString
13+encodeDirect = encode
1614
17−encodeViaValueA :: Result -> L.ByteString
18−encodeViaValueA = encode . toJSON
19−
20−encodeDirectB :: Result -> L.ByteString
21−encodeDirectB = B.encode
22−
23−encodeViaValueB :: Result -> L.ByteString
24−encodeViaValueB = B.encode . B.toJSON
15+encodeViaValue :: Result -> L.ByteString
16+encodeViaValue = encode . toJSON
2517
2618benchmarks :: Benchmark
2719benchmarks =
2820 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
2921 bgroup "encodeGeneric" [
3022 bgroup "direct" [
31− bench "twitter100" $ nf encodeDirectB twitter100
32− , bench "jp100" $ nf encodeDirectB jp100
33− , bench "twitter100 baseline" $ nf encodeDirectA twitter100
34− , bench "jp100 baseline" $ nf encodeDirectA jp100
23+ bench "twitter100" $ nf encodeDirect twitter100
24+ , bench "jp100" $ nf encodeDirect jp100
3525 ]
3626 , bgroup "viaValue" [
37− bench "twitter100" $ nf encodeViaValueB twitter100
38− , bench "jp100" $ nf encodeViaValueB jp100
39− , bench "twitter100 baseline" $ nf encodeViaValueA twitter100
40− , bench "jp100 baseline" $ nf encodeViaValueA jp100
27+ bench "twitter100" $ nf encodeViaValue twitter100
28+ , bench "jp100" $ nf encodeViaValue jp100
4129 ]
4230 ]
4331
44−decodeDirectA :: L.ByteString -> Maybe Result
45−decodeDirectA = decode
46−
47−decodeDirectB :: L.ByteString -> Maybe Result
48−decodeDirectB = B.decode
32+decodeDirect :: L.ByteString -> Maybe Result
33+decodeDirect = decode
4934
5035decodeBenchmarks :: Benchmark
5136decodeBenchmarks =
5237 env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
5338 bgroup "decodeGeneric"
5439 [ bgroup "direct"
55− [ bench "twitter100" $ nf decodeDirectB twitter100
56− , bench "jp100" $ nf decodeDirectB jp100
57− , bench "twitter100 baseline" $ nf decodeDirectA twitter100
58− , bench "jp100 baseline" $ nf decodeDirectA jp100
40+ [ bench "twitter100" $ nf decodeDirect twitter100
41+ , bench "jp100" $ nf decodeDirect jp100
5942 ]
6043 ]
benchmarks/Typed/Manual.hs+13−30
@@ -1,60 +1,43 @@
1−{-# LANGUAGE PackageImports #-}
21module Typed.Manual (benchmarks, decodeBenchmarks) where
32
43import Prelude ()
54import Prelude.Compat
65
7−import "aeson" Data.Aeson hiding (Result)
6+import Data.Aeson hiding (Result)
87import Criterion
98import Data.ByteString.Lazy as L
109import Twitter.Manual
1110import Typed.Common
12−import qualified "aeson-benchmarks" Data.Aeson as B
1311
14−encodeDirectA :: Result -> L.ByteString
15−encodeDirectA = encode
12+encodeDirect :: Result -> L.ByteString
13+encodeDirect = encode
1614
17−encodeViaValueA :: Result -> L.ByteString
18−encodeViaValueA = encode . toJSON
19−
20−encodeDirectB :: Result -> L.ByteString
21−encodeDirectB = B.encode
22−
23−encodeViaValueB :: Result -> L.ByteString
24−encodeViaValueB = B.encode . B.toJSON
15+encodeViaValue :: Result -> L.ByteString
16+encodeViaValue = encode . toJSON
2517
2618benchmarks :: Benchmark
2719benchmarks =
2820 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
2921 bgroup "encodeManual" [
3022 bgroup "direct" [
31− bench "twitter100" $ nf encodeDirectB twitter100
32− , bench "jp100" $ nf encodeDirectB jp100
33− , bench "twitter100 baseline" $ nf encodeDirectA twitter100
34− , bench "jp100 baseline" $ nf encodeDirectA jp100
23+ bench "twitter100" $ nf encodeDirect twitter100
24+ , bench "jp100" $ nf encodeDirect jp100
3525 ]
3626 , bgroup "viaValue" [
37− bench "twitter100" $ nf encodeViaValueB twitter100
38− , bench "jp100" $ nf encodeViaValueB jp100
39− , bench "twitter100 baseline" $ nf encodeViaValueA twitter100
40− , bench "jp100 baseline" $ nf encodeViaValueA jp100
27+ bench "twitter100" $ nf encodeViaValue twitter100
28+ , bench "jp100" $ nf encodeViaValue jp100
4129 ]
4230 ]
4331
44−decodeDirectA :: L.ByteString -> Maybe Result
45−decodeDirectA = decode
46−
47−decodeDirectB :: L.ByteString -> Maybe Result
48−decodeDirectB = B.decode
32+decodeDirect :: L.ByteString -> Maybe Result
33+decodeDirect = decode
4934
5035decodeBenchmarks :: Benchmark
5136decodeBenchmarks =
5237 env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
5338 bgroup "decodeManual"
5439 [ bgroup "direct"
55− [ bench "twitter100" $ nf decodeDirectB twitter100
56− , bench "jp100" $ nf decodeDirectB jp100
57− , bench "twitter100 baseline" $ nf decodeDirectA twitter100
58− , bench "jp100 baseline" $ nf decodeDirectA jp100
40+ [ bench "twitter100" $ nf decodeDirect twitter100
41+ , bench "jp100" $ nf decodeDirect jp100
5942 ]
6043 ]
benchmarks/Typed/TH.hs+13−30
@@ -1,60 +1,43 @@
1−{-# LANGUAGE PackageImports #-}
21module Typed.TH (benchmarks, decodeBenchmarks) where
32
43import Prelude ()
54import Prelude.Compat
65
7−import "aeson" Data.Aeson hiding (Result)
6+import Data.Aeson hiding (Result)
87import Criterion
98import Data.ByteString.Lazy as L
109import Twitter.TH
1110import Typed.Common
12−import qualified "aeson-benchmarks" Data.Aeson as B
1311
14−encodeDirectA :: Result -> L.ByteString
15−encodeDirectA = encode
12+encodeDirect :: Result -> L.ByteString
13+encodeDirect = encode
1614
17−encodeViaValueA :: Result -> L.ByteString
18−encodeViaValueA = encode . toJSON
19−
20−encodeDirectB :: Result -> L.ByteString
21−encodeDirectB = B.encode
22−
23−encodeViaValueB :: Result -> L.ByteString
24−encodeViaValueB = B.encode . B.toJSON
15+encodeViaValue :: Result -> L.ByteString
16+encodeViaValue = encode . toJSON
2517
2618benchmarks :: Benchmark
2719benchmarks =
2820 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
2921 bgroup "encodeTH" [
3022 bgroup "direct" [
31− bench "twitter100" $ nf encodeDirectB twitter100
32− , bench "jp100" $ nf encodeDirectB jp100
33− , bench "twitter100 baseline" $ nf encodeDirectA twitter100
34− , bench "jp100 baseline" $ nf encodeDirectA jp100
23+ bench "twitter100" $ nf encodeDirect twitter100
24+ , bench "jp100" $ nf encodeDirect jp100
3525 ]
3626 , bgroup "viaValue" [
37− bench "twitter100" $ nf encodeViaValueA twitter100
38− , bench "jp100" $ nf encodeViaValueA jp100
39− , bench "twitter100 baseline" $ nf encodeViaValueB twitter100
40− , bench "jp100 baseline" $ nf encodeViaValueB jp100
27+ bench "twitter100" $ nf encodeViaValue twitter100
28+ , bench "jp100" $ nf encodeViaValue jp100
4129 ]
4230 ]
4331
44−decodeDirectA :: L.ByteString -> Maybe Result
45−decodeDirectA = decode
46−
47−decodeDirectB :: L.ByteString -> Maybe Result
48−decodeDirectB = B.decode
32+decodeDirect :: L.ByteString -> Maybe Result
33+decodeDirect = decode
4934
5035decodeBenchmarks :: Benchmark
5136decodeBenchmarks =
5237 env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
5338 bgroup "decodeTH"
5439 [ bgroup "direct"
55− [ bench "twitter100" $ nf decodeDirectB twitter100
56− , bench "jp100" $ nf decodeDirectB jp100
57− , bench "twitter100 baseline" $ nf decodeDirectA twitter100
58− , bench "jp100 baseline" $ nf decodeDirectA jp100
40+ [ bench "twitter100" $ nf decodeDirect twitter100
41+ , bench "jp100" $ nf decodeDirect jp100
5942 ]
6043 ]
benchmarks/aeson-benchmarks.cabal+99−76
@@ -8,59 +8,14 @@ flag bytestring-builder
88 default: False
99 manual: False
1010
11+flag local-aeson
12+ description: Build the local version of aeson, to avoid rebuilding aeson's
13+ reverse dependencies for benchmarking (statistics, criterion).
14+ default: True
15+ manual: True
16+
1117library
1218 default-language: Haskell2010
13− hs-source-dirs: .. . ../ffi ../pure ../attoparsec-iso8601
14− c-sources: ../cbits/unescape_string.c
15− exposed-modules:
16− Data.Aeson
17− Data.Aeson.Compat
18− Data.Aeson.Encoding
19− Data.Aeson.Encoding.Builder
20− Data.Aeson.Encoding.Internal
21− Data.Aeson.Internal
22− Data.Aeson.Internal.Functions
23− Data.Aeson.Internal.Time
24− Data.Aeson.Parser
25− Data.Aeson.Parser.Internal
26− Data.Aeson.Parser.Time
27− Data.Aeson.Parser.Unescape
28− Data.Aeson.Parser.UnescapeFFI
29− Data.Aeson.Parser.UnescapePure
30− Data.Aeson.TH
31− Data.Aeson.Text
32− Data.Aeson.Types
33− Data.Aeson.Types.Class
34− Data.Aeson.Types.FromJSON
35− Data.Aeson.Types.Generic
36− Data.Aeson.Types.Internal
37− Data.Aeson.Types.ToJSON
38− Data.Attoparsec.Time
39− Data.Attoparsec.Time.Internal
40−
41− build-depends:
42− attoparsec >= 0.13.0.1,
43− base == 4.*,
44− base-compat >= 0.9.1 && <0.10,
45− time-locale-compat >=0.1.1 && <0.2,
46− containers,
47− deepseq,
48− dlist >= 0.2,
49− fail == 4.9.*,
50− ghc-prim >= 0.2,
51− hashable >= 1.1.2.0,
52− mtl,
53− scientific >= 0.3.4.7 && < 0.4,
54− syb,
55− tagged >=0.8.3 && <0.9,
56− template-haskell >= 2.4,
57− text >= 1.1.1.0,
58− th-abstraction >= 0.2.2 && < 0.3,
59− time,
60− transformers,
61− unordered-containers >= 0.2.3.0,
62− uuid-types >= 1.0.3 && <1.1,
63− vector >= 0.7.1
6419
6520 if flag(bytestring-builder)
6621 build-depends: bytestring >= 0.9 && < 0.10.4,
@@ -68,17 +23,87 @@ library
6823 else
6924 build-depends: bytestring >= 0.10.4
7025
71− if impl(ghc >=7.8)
72− cpp-options: -DHAS_COERCIBLE
26+ if flag(local-aeson)
27+
28+ hs-source-dirs: .. ../ffi ../pure ../attoparsec-iso8601
29+ c-sources: ../cbits/unescape_string.c
30+ build-depends:
31+ attoparsec >= 0.13.0.1,
32+ base == 4.*,
33+ base-compat >= 0.9.1 && <0.10,
34+ time-locale-compat >=0.1.1 && <0.2,
35+ containers,
36+ deepseq,
37+ dlist >= 0.2,
38+ fail == 4.9.*,
39+ ghc-prim >= 0.2,
40+ hashable >= 1.1.2.0,
41+ mtl,
42+ scientific >= 0.3.4.7 && < 0.4,
43+ syb,
44+ tagged >=0.8.3 && <0.9,
45+ template-haskell >= 2.4,
46+ text >= 1.1.1.0,
47+ th-abstraction >= 0.2.2 && < 0.3,
48+ time,
49+ transformers,
50+ unordered-containers >= 0.2.3.0,
51+ uuid-types >= 1.0.3 && <1.1,
52+ vector >= 0.7.1
7353
74− if !impl(ghc >= 8.0)
75− -- `Data.Semigroup` is available in base only since GHC 8.0 / base 4.9
76− build-depends: semigroups >= 0.18.2 && < 0.19
54+ if !impl(ghc >= 7.10)
55+ -- `Numeric.Natural` is available in base only since GHC 7.10 / base 4.8
56+ build-depends: nats >= 1 && < 1.2
7757
78− include-dirs: ../include
58+ if impl(ghc >=7.8)
59+ cpp-options: -DHAS_COERCIBLE
60+
61+ if !impl(ghc >= 8.0)
62+ -- `Data.Semigroup` is available in base only since GHC 8.0 / base 4.9
63+ build-depends: semigroups >= 0.18.2 && < 0.19
64+
65+ include-dirs: ../include
66+
67+ ghc-options: -O2 -Wall
68+ cpp-options: -DGENERICS
69+
70+ exposed-modules:
71+ Data.Aeson
72+ Data.Aeson.Compat
73+ Data.Aeson.Encoding
74+ Data.Aeson.Encoding.Builder
75+ Data.Aeson.Encoding.Internal
76+ Data.Aeson.Internal
77+ Data.Aeson.Internal.Functions
78+ Data.Aeson.Internal.Time
79+ Data.Aeson.Parser
80+ Data.Aeson.Parser.Internal
81+ Data.Aeson.Parser.Time
82+ Data.Aeson.Parser.Unescape
83+ Data.Aeson.Parser.UnescapeFFI
84+ Data.Aeson.Parser.UnescapePure
85+ Data.Aeson.TH
86+ Data.Aeson.Text
87+ Data.Aeson.Types
88+ Data.Aeson.Types.Class
89+ Data.Aeson.Types.FromJSON
90+ Data.Aeson.Types.Generic
91+ Data.Aeson.Types.Internal
92+ Data.Aeson.Types.ToJSON
93+ Data.Attoparsec.Time
94+ Data.Attoparsec.Time.Internal
95+
96+ else
7997
80− ghc-options: -O2 -Wall
81− cpp-options: -DGENERICS
98+ build-depends: aeson
99+
100+ reexported-modules:
101+ Data.Aeson,
102+ Data.Aeson.Encoding,
103+ Data.Aeson.Parser.Internal,
104+ Data.Aeson.Text,
105+ Data.Aeson.TH,
106+ Data.Aeson.Types
82107
83108executable aeson-benchmark-auto-compare
84109 default-language: Haskell2010
@@ -107,15 +132,19 @@ executable aeson-benchmark-escape
107132 main-is: Escape.hs
108133 hs-source-dirs: ../examples .
109134 ghc-options: -Wall -O2 -rtsopts
110− build-depends:
111− aeson-benchmarks,
112− base,
113− base-compat,
114− bytestring,
115− criterion >= 1.0,
116− deepseq,
117− ghc-prim,
118− text
135+ if flag(local-aeson)
136+ build-depends:
137+ aeson-benchmarks,
138+ base,
139+ base-compat,
140+ bytestring,
141+ criterion >= 1.0,
142+ deepseq,
143+ ghc-prim,
144+ text
145+ else
146+ -- Disabled because of inaccessible internals
147+ buildable: False
119148
120149executable aeson-benchmark-compare
121150 default-language: Haskell2010
@@ -161,9 +190,6 @@ executable aeson-benchmark-typed
161190 main-is: Typed.hs
162191 hs-source-dirs: ../examples .
163192 ghc-options: -Wall -O2 -rtsopts
164− -- We must help ourself in situations when there is both
165− -- aeson and aeson-benchmakrs
166− cpp-options: -DHAS_BOTH_AESON_AND_BENCHMARKS
167193 other-modules:
168194 Twitter
169195 Twitter.Generic
@@ -175,7 +201,6 @@ executable aeson-benchmark-typed
175201 Typed.Manual
176202 Typed.TH
177203 build-depends:
178− aeson,
179204 aeson-benchmarks,
180205 base,
181206 base-compat,
@@ -195,9 +220,7 @@ executable aeson-benchmark-compare-with-json
195220 default-language: Haskell2010
196221 main-is: CompareWithJSON.hs
197222 ghc-options: -Wall -O2 -rtsopts
198− cpp-options: -DHAS_BOTH_AESON_AND_BENCHMARKS
199223 build-depends:
200− aeson,
201224 aeson-benchmarks,
202225 base,
203226 base-compat,
@@ -257,13 +280,14 @@ executable aeson-benchmark-dates
257280 aeson-benchmarks,
258281 text,
259282 time
283+ if impl(ghc >= 8.2)
284+ ghc-options: -Wno-simplifiable-class-constraints
260285
261286executable aeson-benchmark-map
262287 default-language: Haskell2010
263288 main-is: AesonMap.hs
264289 ghc-options: -Wall -O2 -rtsopts
265290 build-depends:
266− aeson,
267291 aeson-benchmarks,
268292 base,
269293 base-compat,
@@ -281,7 +305,6 @@ executable aeson-benchmark-foldable
281305 main-is: AesonFoldable.hs
282306 ghc-options: -Wall -O2 -rtsopts
283307 build-depends:
284− aeson,
285308 aeson-benchmarks,
286309 base,
287310 base-compat,
examples/Twitter/Generic.hs−36
@@ -1,12 +1,7 @@
11-- Use GHC generics to automatically generate good instances.
22
3−{-# LANGUAGE CPP #-}
43{-# OPTIONS_GHC -fno-warn-orphans #-}
54
6−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
7−{-# LANGUAGE PackageImports #-}
8−#endif
9−
105module Twitter.Generic
116 (
127 Metadata(..)
@@ -21,12 +16,7 @@ import Prelude.Compat ()
2116import Twitter
2217import Twitter.Options
2318
24−#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
2519import Data.Aeson (ToJSON (..), FromJSON (..), genericToJSON, genericToEncoding, genericParseJSON)
26−#else
27−import "aeson" Data.Aeson (ToJSON (..), FromJSON (..), genericToJSON, genericToEncoding, genericParseJSON)
28−import qualified "aeson-benchmarks" Data.Aeson as B
29−#endif
3020
3121instance ToJSON Metadata where
3222 toJSON = genericToJSON twitterOptions
@@ -51,29 +41,3 @@ instance ToJSON Result where
5141 toEncoding = genericToEncoding twitterOptions
5242instance FromJSON Result where
5343 parseJSON = genericParseJSON twitterOptions
54−
55−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
56−instance B.ToJSON Metadata where
57− toJSON = B.genericToJSON btwitterOptions
58− toEncoding = B.genericToEncoding btwitterOptions
59−instance B.FromJSON Metadata where
60− parseJSON = B.genericParseJSON btwitterOptions
61−
62−instance B.ToJSON Geo where
63− toJSON = B.genericToJSON btwitterOptions
64− toEncoding = B.genericToEncoding btwitterOptions
65−instance B.FromJSON Geo where
66− parseJSON = B.genericParseJSON btwitterOptions
67−
68−instance B.ToJSON Story where
69− toJSON = B.genericToJSON btwitterOptions
70− toEncoding = B.genericToEncoding btwitterOptions
71−instance B.FromJSON Story where
72− parseJSON = B.genericParseJSON btwitterOptions
73−
74−instance B.ToJSON Result where
75− toJSON = B.genericToJSON btwitterOptions
76− toEncoding = B.genericToEncoding btwitterOptions
77−instance B.FromJSON Result where
78− parseJSON = B.genericParseJSON btwitterOptions
79−#endif
examples/Twitter/Manual.hs−135
@@ -1,14 +1,9 @@
11-- Manually write instances.
22
3−{-# LANGUAGE CPP #-}
43{-# LANGUAGE OverloadedStrings #-}
54{-# LANGUAGE RecordWildCards #-}
65{-# OPTIONS_GHC -fno-warn-orphans #-}
76
8−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
9−{-# LANGUAGE PackageImports #-}
10−#endif
11−
127module Twitter.Manual
138 (
149 Metadata(..)
@@ -25,12 +20,7 @@ import Data.Monoid ((<>))
2520import Prelude hiding (id)
2621import Twitter
2722
28−#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
2923import Data.Aeson hiding (Result)
30−#else
31−import "aeson" Data.Aeson hiding (Result)
32−import qualified "aeson-benchmarks" Data.Aeson as B
33−#endif
3424
3525instance ToJSON Metadata where
3626
@@ -155,128 +145,3 @@ instance FromJSON Result where
155145 <*> v .: "max_id_str"
156146 <*> v .: "query"
157147 parseJSON _ = empty
158−
159−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
160−instance B.ToJSON Metadata where
161− toJSON Metadata{..} = B.object [
162− "result_type" B..= result_type
163− ]
164−
165− toEncoding Metadata{..} = B.pairs $
166− "result_type" B..= result_type
167−
168−instance B.FromJSON Metadata where
169− parseJSON (B.Object v) = Metadata <$> v B..: "result_type"
170− parseJSON _ = empty
171−
172−instance B.ToJSON Geo where
173− toJSON Geo{..} = B.object [
174− "type_" B..= type_
175− , "coordinates" B..= coordinates
176− ]
177−
178− toEncoding Geo{..} = B.pairs $
179− "type_" B..= type_
180− <> "coordinates" B..= coordinates
181−
182−instance B.FromJSON Geo where
183− parseJSON (B.Object v) = Geo <$>
184− v B..: "type_"
185− <*> v B..: "coordinates"
186− parseJSON _ = empty
187−
188−instance B.ToJSON Story where
189− toJSON Story{..} = B.object [
190− "from_user_id_str" B..= from_user_id_str
191− , "profile_image_url" B..= profile_image_url
192− , "created_at" B..= created_at
193− , "from_user" B..= from_user
194− , "id_str" B..= id_str
195− , "metadata" B..= metadata
196− , "to_user_id" B..= to_user_id
197− , "text" B..= text
198− , "id" B..= id_
199− , "from_user_id" B..= from_user_id
200− , "geo" B..= geo
201− , "iso_language_code" B..= iso_language_code
202− , "to_user_id_str" B..= to_user_id_str
203− , "source" B..= source
204− ]
205−
206− toEncoding Story{..} = B.pairs $
207− "from_user_id_str" B..= from_user_id_str
208− <> "profile_image_url" B..= profile_image_url
209− <> "created_at" B..= created_at
210− <> "from_user" B..= from_user
211− <> "id_str" B..= id_str
212− <> "metadata" B..= metadata
213− <> "to_user_id" B..= to_user_id
214− <> "text" B..= text
215− <> "id" B..= id_
216− <> "from_user_id" B..= from_user_id
217− <> "geo" B..= geo
218− <> "iso_language_code" B..= iso_language_code
219− <> "to_user_id_str" B..= to_user_id_str
220− <> "source" B..= source
221−
222−instance B.FromJSON Story where
223− parseJSON (B.Object v) = Story <$>
224− v B..: "from_user_id_str"
225− <*> v B..: "profile_image_url"
226− <*> v B..: "created_at"
227− <*> v B..: "from_user"
228− <*> v B..: "id_str"
229− <*> v B..: "metadata"
230− <*> v B..: "to_user_id"
231− <*> v B..: "text"
232− <*> v B..: "id"
233− <*> v B..: "from_user_id"
234− <*> v B..: "geo"
235− <*> v B..: "iso_language_code"
236− <*> v B..: "to_user_id_str"
237− <*> v B..: "source"
238− parseJSON _ = empty
239−
240−instance B.ToJSON Result where
241− toJSON Result{..} = B.object [
242− "results" B..= results
243− , "max_id" B..= max_id
244− , "since_id" B..= since_id
245− , "refresh_url" B..= refresh_url
246− , "next_page" B..= next_page
247− , "results_per_page" B..= results_per_page
248− , "page" B..= page
249− , "completed_in" B..= completed_in
250− , "since_id_str" B..= since_id_str
251− , "max_id_str" B..= max_id_str
252− , "query" B..= query
253− ]
254−
255− toEncoding Result{..} = B.pairs $
256− "results" B..= results
257− <> "max_id" B..= max_id
258− <> "since_id" B..= since_id
259− <> "refresh_url" B..= refresh_url
260− <> "next_page" B..= next_page
261− <> "results_per_page" B..= results_per_page
262− <> "page" B..= page
263− <> "completed_in" B..= completed_in
264− <> "since_id_str" B..= since_id_str
265− <> "max_id_str" B..= max_id_str
266− <> "query" B..= query
267−
268−instance B.FromJSON Result where
269− parseJSON (B.Object v) = Result <$>
270− v B..: "results"
271− <*> v B..: "max_id"
272− <*> v B..: "since_id"
273− <*> v B..: "refresh_url"
274− <*> v B..: "next_page"
275− <*> v B..: "results_per_page"
276− <*> v B..: "page"
277− <*> v B..: "completed_in"
278− <*> v B..: "since_id_str"
279− <*> v B..: "max_id_str"
280− <*> v B..: "query"
281− parseJSON _ = empty
282−#endif
examples/Twitter/Options.hs−21
@@ -1,18 +1,6 @@
1−{-# LANGUAGE CPP #-}
2−
3−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
4−{-# LANGUAGE PackageImports #-}
5−#endif
6−
71module Twitter.Options (module Twitter.Options) where
82
9−#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
103import Data.Aeson
11−import Data.Aeson.Types
12−#else
13−import "aeson" Data.Aeson
14−import qualified "aeson-benchmarks" Data.Aeson as B
15−#endif
164
175twitterOptions :: Options
186twitterOptions = defaultOptions
@@ -20,12 +8,3 @@ twitterOptions = defaultOptions
208 "id_" -> "id"
219 _ -> x
2210 }
23−
24−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
25−btwitterOptions :: B.Options
26−btwitterOptions = B.defaultOptions
27− { B.fieldLabelModifier = \x -> case x of
28− "id_" -> "id"
29− _ -> x
30− }
31−#endif
examples/Twitter/TH.hs−17
@@ -1,13 +1,8 @@
11-- Use Template Haskell to generate good instances.
22
3−{-# LANGUAGE CPP #-}
43{-# LANGUAGE TemplateHaskell #-}
54{-# OPTIONS_GHC -fno-warn-orphans #-}
65
7−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
8−{-# LANGUAGE PackageImports #-}
9−#endif
10−
116module Twitter.TH
127 (
138 Metadata(..)
@@ -21,21 +16,9 @@ import Prelude ()
2116import Twitter
2217import Twitter.Options
2318
24−#ifndef HAS_BOTH_AESON_AND_BENCHMARKS
2519import Data.Aeson.TH
26−#else
27−import "aeson" Data.Aeson.TH
28−import qualified "aeson-benchmarks" Data.Aeson.TH as B
29−#endif
3020
3121$(deriveJSON twitterOptions ''Metadata)
3222$(deriveJSON twitterOptions ''Geo)
3323$(deriveJSON twitterOptions ''Story)
3424$(deriveJSON twitterOptions ''Result)
35−
36−#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
37−$(B.deriveJSON btwitterOptions ''Metadata)
38−$(B.deriveJSON btwitterOptions ''Geo)
39−$(B.deriveJSON btwitterOptions ''Story)
40−$(B.deriveJSON btwitterOptions ''Result)
41−#endif