packages feed

winery 0.1 → 0.1.1

raw patch · 6 files changed

+199/−79 lines, 6 filesdep +cpudep +fingertreedep −fast-builder

Dependencies added: cpu, fingertree

Dependencies removed: fast-builder

Files

README.md view
@@ -3,8 +3,7 @@ winery is a serialisation library for Haskell. It tries to achieve two goals: compact representation and perpetual inspectability. -The `binary` library provides a compact representation, but there is no way to-inspect the serialised value without the original instance.+The standard `binary` library has no way to inspect the serialised value without the original instance.  There's `serialise`, which is an alternative library based on CBOR. Every value has to be accompanied with tags, so it tends to be redundant for arrays of small values. Encoding records with field names is also redudant. @@ -114,3 +113,31 @@ , foo: Just 42 } ```++## Benchmark++```haskell+data TestRec = TestRec+  { id_ :: !Int+  , first_name :: !Text+  , last_name :: !Text+  , email :: !Text+  , gender :: !Gender+  , num :: !Int+  , latitude :: !Double+  , longitude :: !Double+  } deriving (Show, Generic)+```++(De)serialisation of the datatype above using generic instances:++```+serialise/winery                         mean 658.6 μs  ( +- 45.04 μs  )+serialise/binary                         mean 1.056 ms  ( +- 58.95 μs  )+serialise/serialise                      mean 258.8 μs  ( +- 5.654 μs  )+deserialise/winery                       mean 706.4 μs  ( +- 52.41 μs  )+deserialise/binary                       mean 1.393 ms  ( +- 56.71 μs  )+deserialise/serialise                    mean 765.8 μs  ( +- 30.26 μs  )+```++Not bad, considering that binary and serialise don't encode field names.
benchmarks/bench.hs view
@@ -46,7 +46,7 @@   winery <- B.readFile "benchmarks/data.winery"   binary <- B.readFile "benchmarks/data.binary"   cbor <- B.readFile "benchmarks/data.cbor"-  Right (values :: [TestRec]) <- return $ deserialise winery+  values :: [TestRec] <- return $ B.decode $ BL.fromStrict binary   defaultMain     [ bgroup "serialise"       [ bench "winery" $ nf serialise values
src/Data/Winery.hs view
@@ -12,6 +12,7 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE StandaloneDeriving #-} module Data.Winery   ( Schema(..)   , Serialise(..)@@ -59,7 +60,7 @@ import Control.Monad.Trans.Cont import Control.Monad.Reader import qualified Data.ByteString as B-import qualified Data.ByteString.FastBuilder as BB+import qualified Data.Winery.Internal.Builder as BB import Data.Bits import Data.Dynamic import Data.Functor.Compose@@ -216,8 +217,9 @@  -- | Serialise a value along with its schema. serialise :: Serialise a => a -> B.ByteString-serialise a = BB.toStrictByteString $ mappend (BB.word8 currentSchemaVersion)-  $ encodingBuilder $ toEncoding (schema [a], a)+serialise a = BB.toByteString $ mappend (BB.word8 currentSchemaVersion)+  $ toEncoding (schema [a], a)+{-# INLINE serialise #-}  -- | Deserialise a 'serialise'd 'B.Bytestring'. deserialise :: Serialise a => B.ByteString -> Either StrategyError a@@ -232,7 +234,7 @@  -- | Serialise a value without its schema. serialiseOnly :: Serialise a => a -> B.ByteString-serialiseOnly = BB.toStrictByteString . encodingBuilder . toEncoding+serialiseOnly = BB.toByteString . toEncoding {-# INLINE serialiseOnly #-}  substSchema :: Serialise a => Proxy a -> [TypeRep] -> Schema@@ -298,8 +300,8 @@  instance Serialise Bool where   schemaVia _ _ = SBool-  toEncoding False = Encoding 1 (BB.word8 0)-  toEncoding True = Encoding 1 (BB.word8 1)+  toEncoding False = BB.word8 0+  toEncoding True = BB.word8 1   deserialiser = Deserialiser $ Plan $ \case     SBool -> pure $ (/=0) <$> evalContT getWord8     s -> unexpectedSchema "Serialise Bool" s@@ -307,7 +309,7 @@  instance Serialise Word8 where   schemaVia _ _ = SWord8-  toEncoding x = Encoding 1 (BB.word8 x)+  toEncoding = BB.word8   deserialiser = Deserialiser $ Plan $ \case     SWord8 -> pure $ evalContT getWord8     s -> unexpectedSchema "Serialise Word8" s@@ -315,7 +317,7 @@  instance Serialise Word16 where   schemaVia _ _ = SWord16-  toEncoding x = Encoding 2 (BB.word16BE x)+  toEncoding = BB.word16   deserialiser = Deserialiser $ Plan $ \case     SWord16 -> pure $ evalContT $ do       a <- getWord8@@ -326,7 +328,7 @@  instance Serialise Word32 where   schemaVia _ _ = SWord32-  toEncoding x = Encoding 4 (BB.word32BE x)+  toEncoding = BB.word32   deserialiser = Deserialiser $ Plan $ \case     SWord32 -> pure word32be     s -> unexpectedSchema "Serialise Word32" s@@ -334,7 +336,7 @@  instance Serialise Word64 where   schemaVia _ _ = SWord64-  toEncoding x = Encoding 8 (BB.word64BE x)+  toEncoding = BB.word64   deserialiser = Deserialiser $ Plan $ \case     SWord64 -> pure word64be     s -> unexpectedSchema "Serialise Word64" s@@ -342,7 +344,7 @@  instance Serialise Word where   schemaVia _ _ = SWord64-  toEncoding x = Encoding 8 $ BB.word64BE $ fromIntegral x+  toEncoding = BB.word64 . fromIntegral   deserialiser = Deserialiser $ Plan $ \case     SWord64 -> pure $ fromIntegral <$> word64be     s -> unexpectedSchema "Serialise Word" s@@ -350,7 +352,7 @@  instance Serialise Int8 where   schemaVia _ _ = SInt8-  toEncoding x = Encoding 1 (BB.int8 x)+  toEncoding = BB.word8 . fromIntegral   deserialiser = Deserialiser $ Plan $ \case     SInt8 -> pure $ fromIntegral <$> evalContT getWord8     s -> unexpectedSchema "Serialise Int8" s@@ -358,7 +360,7 @@  instance Serialise Int16 where   schemaVia _ _ = SInt16-  toEncoding x = Encoding 2 (BB.int16BE x)+  toEncoding = BB.word16 . fromIntegral   deserialiser = Deserialiser $ Plan $ \case     SInt16 -> pure $ fromIntegral <$> word16be     s -> unexpectedSchema "Serialise Int16" s@@ -366,7 +368,7 @@  instance Serialise Int32 where   schemaVia _ _ = SInt32-  toEncoding x = Encoding 4 (BB.int32BE x)+  toEncoding = BB.word32 . fromIntegral   deserialiser = Deserialiser $ Plan $ \case     SInt32 -> pure $ fromIntegral <$> word32be     s -> unexpectedSchema "Serialise Int32" s@@ -374,7 +376,7 @@  instance Serialise Int64 where   schemaVia _ _ = SInt64-  toEncoding x = Encoding 8 (BB.int64BE x)+  toEncoding = BB.word64 . fromIntegral   deserialiser = Deserialiser $ Plan $ \case     SInt64 -> pure $ fromIntegral <$> word64be     s -> unexpectedSchema "Serialise Int64" s@@ -389,7 +391,7 @@  instance Serialise Float where   schemaVia _ _ = SFloat-  toEncoding x = Encoding 4 $ BB.word32BE $ unsafeCoerce x+  toEncoding = BB.word32 . unsafeCoerce   deserialiser = Deserialiser $ Plan $ \case     SFloat -> pure $ unsafeCoerce <$> word32be     s -> unexpectedSchema "Serialise Float" s@@ -397,7 +399,7 @@  instance Serialise Double where   schemaVia _ _ = SDouble-  toEncoding x = Encoding 8 $ BB.word64BE $ unsafeCoerce x+  toEncoding = BB.word64 . unsafeCoerce   deserialiser = Deserialiser $ Plan $ \case     SDouble -> pure $ unsafeCoerce <$> word64be     s -> unexpectedSchema "Serialise Double" s@@ -452,7 +454,7 @@  instance Serialise B.ByteString where   schemaVia _ _ = SBytes-  toEncoding bs = Encoding (B.length bs) (BB.byteString bs)+  toEncoding = BB.bytes   deserialiser = Deserialiser $ Plan $ \case     SBytes -> pure id     s -> unexpectedSchema "Serialise ByteString" s@@ -463,7 +465,7 @@     Just s -> SArray (VarInt s) (substSchema (Proxy :: Proxy a) ts)   toEncoding xs = case constantSize (Proxy :: Proxy a) of     Nothing -> encodeVarInt (length xs)-      <> encodeMulti (map toEncoding xs)+      <> encodeMulti (\r -> foldr (encodeItem . toEncoding) r xs)     Just _ -> encodeVarInt (length xs) <> foldMap toEncoding xs   deserialiser = extractListWith deserialiser @@ -528,12 +530,6 @@   toEncoding = toEncoding . toList   deserialiser = Seq.fromList <$> deserialiser -instance Serialise a => Serialise (Identity a) where-  schemaVia _ = schemaVia (Proxy :: Proxy a)-  toEncoding = toEncoding . runIdentity-  deserialiser = Identity <$> deserialiser-  constantSize _ = constantSize (Proxy :: Proxy a)- -- | Extract a field of a record. extractField :: Serialise a => T.Text -> Deserialiser a extractField = extractFieldWith deserialiser@@ -571,7 +567,7 @@       sa = substSchema (Proxy :: Proxy a) ts       sb = substSchema (Proxy :: Proxy b) ts   toEncoding (a, b) = case constantSize (Proxy :: Proxy (a, b)) of-    Nothing -> encodeMulti [toEncoding a, toEncoding b]+    Nothing -> encodeMulti (encodeItem (toEncoding a) . encodeItem (toEncoding b))     Just _ -> toEncoding a <> toEncoding b   deserialiser = Deserialiser $ Plan $ \case     SProduct [sa, sb] -> do@@ -597,7 +593,7 @@       sb = substSchema (Proxy :: Proxy b) ts       sc = substSchema (Proxy :: Proxy c) ts   toEncoding (a, b, c) = case constantSize (Proxy :: Proxy (a, b, c)) of-    Nothing -> encodeMulti [toEncoding a, toEncoding b, toEncoding c]+    Nothing -> encodeMulti $ encodeItem (toEncoding a) . encodeItem (toEncoding b) . encodeItem (toEncoding c)     Just _ -> toEncoding a <> toEncoding b <> toEncoding c   deserialiser = Deserialiser $ Plan $ \case     SProduct [sa, sb, sc] -> do@@ -627,7 +623,7 @@       sc = substSchema (Proxy :: Proxy c) ts       sd = substSchema (Proxy :: Proxy d) ts   toEncoding (a, b, c, d) = case constantSize (Proxy :: Proxy (a, b, c)) of-    Nothing -> encodeMulti [toEncoding a, toEncoding b, toEncoding c, toEncoding d]+    Nothing -> encodeMulti $ encodeItem (toEncoding a) . encodeItem (toEncoding b) . encodeItem (toEncoding c) . encodeItem (toEncoding d)     Just _ -> toEncoding a <> toEncoding b <> toEncoding c <> toEncoding d   deserialiser = Deserialiser $ Plan $ \case     SProduct [sa, sb, sc, sd] -> do@@ -653,8 +649,8 @@ instance (Serialise a, Serialise b) => Serialise (Either a b) where   schemaVia _ ts = SVariant [("Left", [substSchema (Proxy :: Proxy a) ts])     , ("Right", [substSchema (Proxy :: Proxy b) ts])]-  toEncoding (Left a) = Encoding 1 (BB.word8 0) <> toEncoding a-  toEncoding (Right b) = Encoding 1 (BB.word8 1) <> toEncoding b+  toEncoding (Left a) = BB.word8 0 <> toEncoding a+  toEncoding (Right b) = BB.word8 1 <> toEncoding b   deserialiser = Deserialiser $ Plan $ \case     SVariant [(_, [sa]), (_, [sb])] -> do       getA <- unwrapDeserialiser deserialiser sa@@ -726,16 +722,17 @@   where     rep = "gdeserialiserRecord :: Deserialiser "       <> viaShow (typeRep (Proxy :: Proxy a))+{-# INLINE gdeserialiserRecord #-}  class GEncodeRecord f where-  recordEncoder :: f x -> [Encoding]+  recordEncoder :: f x -> EncodingMulti -> EncodingMulti  instance (GEncodeRecord f, GEncodeRecord g) => GEncodeRecord (f :*: g) where-  recordEncoder (f :*: g) = recordEncoder f ++ recordEncoder g+  recordEncoder (f :*: g) = recordEncoder f . recordEncoder g   {-# INLINE recordEncoder #-}  instance Serialise a => GEncodeRecord (S1 c (K1 i a)) where-  recordEncoder (M1 (K1 a)) = pure $! toEncoding a+  recordEncoder (M1 (K1 a)) = encodeItem (toEncoding a)   {-# INLINE recordEncoder #-}  instance GEncodeRecord f => GEncodeRecord (C1 c f) where@@ -774,17 +771,17 @@  class GSerialiseProduct f where   productSchema :: proxy f -> [TypeRep] -> [Schema]-  productEncoder :: f x -> [Encoding]+  productEncoder :: f x -> EncodingMulti -> EncodingMulti   productDecoder :: TransFusion (FieldDecoder ()) Decoder (Decoder (f x))  instance GSerialiseProduct U1 where   productSchema _ _ = []-  productEncoder _ = []+  productEncoder _ = id   productDecoder = pure (pure U1)  instance (Serialise a) => GSerialiseProduct (K1 i a) where   productSchema _ ts = [substSchema (Proxy :: Proxy a) ts]-  productEncoder (K1 a) = [toEncoding a]+  productEncoder (K1 a) = encodeItem (toEncoding a)   productDecoder = TransFusion $ \k -> fmap (fmap K1) $ k $ FieldDecoder () Nothing (getDeserialiser deserialiser)  instance GSerialiseProduct f => GSerialiseProduct (M1 i c f) where@@ -794,7 +791,7 @@  instance (GSerialiseProduct f, GSerialiseProduct g) => GSerialiseProduct (f :*: g) where   productSchema _ ts = productSchema (Proxy :: Proxy f) ts ++ productSchema (Proxy :: Proxy g) ts-  productEncoder (f :*: g) = productEncoder f ++ productEncoder g+  productEncoder (f :*: g) = productEncoder f . productEncoder g   productDecoder = liftA2 (:*:) <$> productDecoder <*> productDecoder  deserialiserProduct' :: GSerialiseProduct f => [Schema] -> Strategy (Decoder (f x))@@ -870,3 +867,7 @@   variantSchema _ ts = variantSchema (Proxy :: Proxy f) ts   variantEncoder i (M1 a) = variantEncoder i a   variantDecoder = fmap (fmap (fmap (fmap M1))) <$> variantDecoder++instance Serialise Ordering+deriving instance Serialise a => Serialise (Identity a)+deriving instance (Serialise a, Typeable b) => Serialise (Const a (b :: *))
src/Data/Winery/Internal.hs view
@@ -8,8 +8,10 @@ {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilies #-} module Data.Winery.Internal-  ( Encoding(..)+  ( Encoding+  , EncodingMulti   , encodeMulti+  , encodeItem   , encodeVarInt   , Decoder   , decodeAt@@ -35,10 +37,9 @@ import Control.Monad.Fix import Control.Monad.ST import Control.Monad.Trans.Cont-import Data.ByteString.FastBuilder import qualified Data.ByteString as B import qualified Data.ByteString.Unsafe as B-import qualified Data.ByteString.FastBuilder as BB+import Data.Winery.Internal.Builder import Data.Bits import Data.Dynamic import Data.Monoid@@ -48,16 +49,6 @@ import qualified Data.Vector.Unboxed.Mutable as UM import Data.Word -data Encoding = Encoding-  { encodingLength :: !Int, encodingBuilder :: !Builder }--instance Monoid Encoding where-  mempty = Encoding 0 mempty-  mappend (Encoding m a) (Encoding n b) = Encoding (m + n) (mappend a b)--rebuildEncoding :: Encoding -> Encoding-rebuildEncoding (Encoding l b) = Encoding l (BB.rebuild b)- type Decoder = (->) B.ByteString  decodeAt :: (Int, Int) -> Decoder a -> Decoder a@@ -67,17 +58,18 @@ encodeVarInt n   | n < 0 = case negate n of     n'-      | n' < 0x40 -> e1 (fromIntegral n' `setBit` 6)-      | otherwise -> go (e1 (0xc0 .|. fromIntegral n')) (shiftR n' 6)-  | n < 0x40 = e1 (fromIntegral n)-  | otherwise = go (e1 (fromIntegral n `setBit` 7 `clearBit` 6)) (shiftR n 6)-  where-  e1 = Encoding 1 . BB.word8-  go !acc m-    | m < 0x80 = acc `mappend` e1 (fromIntegral m)-    | otherwise = go (acc <> e1 (setBit (fromIntegral m) 7)) (shiftR m 7)-{-# INLINE encodeVarInt #-}+      | n' < 0x40 -> word8 (fromIntegral n' `setBit` 6)+      | otherwise -> encodesUVarInt (word8 (0xc0 .|. fromIntegral n')) (unsafeShiftR n' 6)+  | n < 0x40 = word8 (fromIntegral n)+  | otherwise = encodesUVarInt (word8 (fromIntegral n `setBit` 7 `clearBit` 6)) (unsafeShiftR n 6)+{-# SPECIALISE encodeVarInt :: Int -> Encoding #-} +encodesUVarInt :: (Bits a, Integral a) => Encoding -> a -> Encoding+encodesUVarInt !acc m+  | m < 0x80 = acc `mappend` word8 (fromIntegral m)+  | otherwise = encodesUVarInt (acc <> word8 (setBit (fromIntegral m) 7)) (unsafeShiftR m 7)+{-# SPECIALISE encodesUVarInt :: Encoding -> Int -> Encoding #-}+ getWord8 :: ContT r Decoder Word8 getWord8 = ContT $ \k bs -> case B.uncons bs of   Nothing -> k 0 bs@@ -89,15 +81,15 @@   n | testBit n 7 -> do       m <- getWord8 >>= go       if testBit n 6-        then return $! negate $ shiftL m 6 .|. fromIntegral n .&. 0x3f-        else return $! shiftL m 6 .|. clearBit (fromIntegral n) 7+        then return $! negate $ unsafeShiftL m 6 .|. fromIntegral n .&. 0x3f+        else return $! unsafeShiftL m 6 .|. clearBit (fromIntegral n) 7     | testBit n 6 -> return $ negate $ fromIntegral $ clearBit n 6     | otherwise -> return $ fromIntegral n   where     go n       | testBit n 7 = do         m <- getWord8 >>= go-        return $! shiftL m 7 .|. clearBit (fromIntegral n) 7+        return $! unsafeShiftL m 7 .|. clearBit (fromIntegral n) 7       | otherwise = return $ fromIntegral n {-# INLINE decodeVarInt #-} @@ -130,14 +122,20 @@     (fromIntegral (s `B.unsafeIndex` 7) )   else error $ "word64be" ++ show s -encodeMulti :: [Encoding] -> Encoding-encodeMulti xs = rebuildEncoding-  $ foldMap (encodeVarInt . encodingLength) (safeInit xs) <> mconcat xs-  where-    safeInit [] = []-    safeInit [_] = []-    safeInit (y:ys) = y : safeInit ys+data EncodingMulti = EncodingMulti0+    | EncodingMulti !Encoding !Encoding++encodeMulti :: (EncodingMulti -> EncodingMulti) -> Encoding+encodeMulti f = case f EncodingMulti0 of+  EncodingMulti0 -> mempty+  EncodingMulti r s -> mappend r s {-# INLINE encodeMulti #-}++encodeItem :: Encoding -> EncodingMulti -> EncodingMulti+encodeItem e EncodingMulti0 = EncodingMulti mempty e+encodeItem e (EncodingMulti a b) = EncodingMulti+  (mappend (encodeVarInt (getSize e)) a) (mappend e b)+{-# INLINE encodeItem #-}  type Offsets = U.Vector (Int, Int) 
+ src/Data/Winery/Internal/Builder.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, BangPatterns #-}+module Data.Winery.Internal.Builder+  ( Encoding+  , getSize+  , toByteString+  , word8+  , word16+  , word32+  , word64+  , bytes+  ) where++import qualified Data.ByteString as B+import qualified Data.ByteString.Internal as B+import Data.Word+import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import System.IO.Unsafe+import System.Endian++data Encoding = Encoding {-# UNPACK #-}!Int !Tree+  | Empty++data Tree = Bin Tree Tree+  | LWord8 {-# UNPACK #-} !Word8+  | LWord16 {-# UNPACK #-} !Word16+  | LWord32 {-# UNPACK #-} !Word32+  | LWord64 {-# UNPACK #-} !Word64+  | LBytes !B.ByteString++instance Monoid Encoding where+  mempty = Empty+  {-# INLINE mempty #-}+  mappend Empty a = a+  mappend a Empty = a+  mappend (Encoding s a) (Encoding t b) = Encoding (s + t) (Bin a b)+  {-# INLINE mappend #-}++getSize :: Encoding -> Int+getSize Empty = 0+getSize (Encoding s _) = s+{-# INLINE getSize #-}++toByteString :: Encoding -> B.ByteString+toByteString Empty = B.empty+toByteString (Encoding len tree) = unsafeDupablePerformIO $ do+  fp <- B.mallocByteString len+  withForeignPtr fp $ \ptr -> do+    let copyBS ofs (B.PS fp' sofs len') = withForeignPtr fp'+          $ \src -> B.memcpy (ptr `plusPtr` ofs) (src `plusPtr` sofs) len'+    let go :: Int -> Tree -> IO ()+        go ofs l = case l of+          LWord8 w -> pokeByteOff ptr ofs w+          LWord16 w -> pokeByteOff ptr ofs $ toBE16 w+          LWord32 w -> pokeByteOff ptr ofs $ toBE32 w+          LWord64 w -> pokeByteOff ptr ofs $ toBE64 w+          LBytes bs -> copyBS ofs bs+          Bin a b -> rotate ofs a b++        rotate :: Int -> Tree -> Tree -> IO ()+        rotate ofs (LWord8 w) t = pokeByteOff ptr ofs w >> go (ofs + 1) t+        rotate ofs (LWord16 w) t = pokeByteOff ptr ofs (toBE16 w) >> go (ofs + 2) t+        rotate ofs (LWord32 w) t = pokeByteOff ptr ofs (toBE32 w) >> go (ofs + 4) t+        rotate ofs (LWord64 w) t = pokeByteOff ptr ofs (toBE64 w) >> go (ofs + 8) t+        rotate ofs (LBytes bs) t = copyBS ofs bs >> go (ofs + B.length bs) t+        rotate ofs (Bin c d) t = rotate ofs c (Bin d t)+    go 0 tree+  return (B.PS fp 0 len)++word8 :: Word8 -> Encoding+word8 = Encoding 1 . LWord8+{-# INLINE word8 #-}++word16 :: Word16 -> Encoding+word16 = Encoding 2 . LWord16+{-# INLINE word16 #-}++word32 :: Word32 -> Encoding+word32 = Encoding 4 . LWord32+{-# INLINE word32 #-}++word64 :: Word64 -> Encoding+word64 = Encoding 8 . LWord64+{-# INLINE word64 #-}++bytes :: B.ByteString -> Encoding+bytes bs = Encoding (B.length bs) $ LBytes bs+{-# INLINE bytes #-}
winery.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: cd7f7da4332784c7d2fa7dab5a2c1c418d2f8c00ede5bbb3c1b560a6323fb4a6+-- hash: 750a23f7c3318207ce7adf5a4637dd1630f0e706c5efab6184ecbb0fc4b4882e  name:           winery-version:        0.1+version:        0.1.1 synopsis:       Sustainable serialisation library description:    Please see the README on Github at <https://github.com/fumieval/winery#readme> category:       Data@@ -35,7 +35,8 @@       base >=4.7 && <5     , bytestring     , containers-    , fast-builder+    , cpu+    , fingertree     , hashable     , mtl     , prettyprinter@@ -49,6 +50,7 @@       Data.Winery.Term       Data.Winery.Internal   other-modules:+      Data.Winery.Internal.Builder       Paths_winery   default-language: Haskell2010 @@ -60,7 +62,8 @@       base >=4.7 && <5     , bytestring     , containers-    , fast-builder+    , cpu+    , fingertree     , hashable     , mtl     , prettyprinter@@ -83,7 +86,8 @@       base >=4.7 && <5     , bytestring     , containers-    , fast-builder+    , cpu+    , fingertree     , hashable     , mtl     , prettyprinter@@ -109,8 +113,9 @@     , bytestring     , cassava     , containers+    , cpu     , deepseq-    , fast-builder+    , fingertree     , gauge     , hashable     , mtl