packages feed

generic-deriving 1.11.2 → 1.12

raw patch · 13 files changed

+270/−66 lines, 13 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Generics.Deriving.TH: simplInstance :: Name -> Name -> Name -> Name -> Q [Dec]
+ Generics.Deriving.Copoint: instance Generics.Deriving.Copoint.GCopoint' GHC.Generics.V1
+ Generics.Deriving.Eq: instance Generics.Deriving.Eq.GEq' GHC.Generics.V1
+ Generics.Deriving.Foldable: instance Generics.Deriving.Foldable.GFoldable' GHC.Generics.V1
+ Generics.Deriving.Functor: instance Generics.Deriving.Functor.GFunctor' GHC.Generics.V1
+ Generics.Deriving.Show: instance Generics.Deriving.Show.GShow' GHC.Generics.V1
+ Generics.Deriving.TH: [emptyCaseOptions] :: Options -> EmptyCaseOptions
+ Generics.Deriving.TH: defaultEmptyCaseOptions :: EmptyCaseOptions
+ Generics.Deriving.TH: makeFrom0Options :: EmptyCaseOptions -> Name -> Q Exp
+ Generics.Deriving.TH: makeFrom1Options :: EmptyCaseOptions -> Name -> Q Exp
+ Generics.Deriving.TH: makeTo0Options :: EmptyCaseOptions -> Name -> Q Exp
+ Generics.Deriving.TH: makeTo1Options :: EmptyCaseOptions -> Name -> Q Exp
+ Generics.Deriving.TH: type EmptyCaseOptions = Bool
+ Generics.Deriving.Traversable: instance Generics.Deriving.Traversable.GTraversable' GHC.Generics.V1
- Generics.Deriving.TH: Options :: RepOptions -> KindSigOptions -> Options
+ Generics.Deriving.TH: Options :: RepOptions -> KindSigOptions -> EmptyCaseOptions -> Options

Files

CHANGELOG.md view
@@ -1,3 +1,21 @@+# 1.12 [2017.12.07]+* Adapt to the `EmptyDataDeriving` proposal (introduced in GHC 8.4):+  * `Generics.Deriving.TH` now derives `to(1)` and `from(1)` implementations+    for empty data types that are strict in the argument.+  * Introduce an `EmptyCaseOptions` field to `Options` in+    `Generics.Deriving.TH`, which controls whether generated `from(1)`/`to(1)`+    implementations for empty data types should use the `EmptyCase` extension+    or not (as is the case in GHC 8.4).+  * Add `mkFrom0Options`, `mkFrom1Options`, `mkTo0Options`, and `mkTo1Options`+    functions to `Generics.Deriving.TH`, which take `EmptyCaseOptions` as+    arguments.+  * The backported instances for `V1` are now maximally lazy, as per+    `EmptyDataDeriving`. (Previously, some instances would unnecessarily force+    their argument, such as the `Eq` and `Ord` instances.)+  * Add instances for `V1` in `Generics.Deriving.Copoint`, `.Eq`, `.Foldable`,+    `.Functor`, `.Show`, and `.Traversable`.+* Remove the bitrotting `simplInstance` function from `Generics.Deriving.TH`.+ # 1.11.2 [2017.04.10] * Add `GEq`, `GShow`, `GEnum`, and `GIx` instances for the new data types   in `Foreign.C.Types` (`CBool`) and `System.Posix.Types` (`CBlkSize`,
generic-deriving.cabal view
@@ -1,5 +1,5 @@ name:                   generic-deriving-version:                1.11.2+version:                1.12 synopsis:               Generic programming library for generalised deriving. description: @@ -32,7 +32,7 @@                       , GHC == 7.8.4                       , GHC == 7.10.3                       , GHC == 8.0.2-                      , GHC == 8.2.1+                      , GHC == 8.2.2 extra-source-files:     CHANGELOG.md                       , README.md @@ -84,7 +84,8 @@ test-suite spec   type:                 exitcode-stdio-1.0   main-is:              Spec.hs-  other-modules:        ExampleSpec+  other-modules:        EmptyCaseSpec+                        ExampleSpec                         TypeInTypeSpec   build-depends:        base             >= 4.3  && < 5                       , generic-deriving
src/Generics/Deriving/Base/Internal.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFunctor #-}@@ -627,7 +628,7 @@ import Control.Applicative ( Alternative(..) ) import Control.Monad ( MonadPlus(..) ) import Control.Monad.Fix ( MonadFix(..), fix )-import Data.Data ( Data )+import Data.Data ( Data(..), DataType, constrIndex, mkDataType ) import Data.Ix ( Ix ) import Text.ParserCombinators.ReadPrec (pfail) import Text.Read ( Read(..), parens, readListDefault, readListPrecDefault )@@ -653,13 +654,39 @@ --------------------------------------------------------------------------------  -- | Void: used for datatypes without constructors-data V1 p-  deriving (Functor, Foldable, Traversable, Typeable)+data V1 p deriving Typeable -deriving instance           Eq   (V1 p)-deriving instance Data p => Data (V1 p)-deriving instance           Ord  (V1 p)-deriving instance           Show (V1 p)+-- Implement these instances by hand to get the desired, maximally lazy behavior.+instance Functor V1 where+  fmap _ !_ = error "Void fmap"++instance Foldable V1 where+  foldr _ z _ = z+  foldMap _ _ = mempty++instance Traversable V1 where+  traverse _ x = pure (case x of !_ -> error "Void traverse")++instance Eq (V1 p) where+  _ == _ = True++instance Data p => Data (V1 p) where+  gfoldl _ _ !_ = error "Void gfoldl"+  gunfold _ _ c = case constrIndex c of+                    _ -> error "Void gunfold"+  toConstr !_ = error "Void toConstr"+  dataTypeOf _ = v1DataType+  dataCast1 f = gcast1 f++v1DataType :: DataType+v1DataType = mkDataType "V1" []++instance Ord (V1 p) where+  compare _ _ = EQ++instance Show (V1 p) where+  showsPrec _ !_ = error "Void showsPrec"+ -- Implement Read instance manually to get around an old GHC bug -- (Trac #7931) instance Read (V1 p) where
src/Generics/Deriving/Copoint.hs view
@@ -50,6 +50,9 @@ class GCopoint' t where     gcopoint' :: t a -> Maybe a +instance GCopoint' V1 where+    gcopoint' _ = Nothing+ instance GCopoint' U1 where     gcopoint' U1 = Nothing 
src/Generics/Deriving/Eq.hs view
@@ -82,6 +82,9 @@ class GEq' f where   geq' :: f a -> f a -> Bool +instance GEq' V1 where+  geq' _ _ = True+ instance GEq' U1 where   geq' _ _ = True 
src/Generics/Deriving/Foldable.hs view
@@ -80,6 +80,9 @@ class GFoldable' t where   gfoldMap' :: Monoid m => (a -> m) -> t a -> m +instance GFoldable' V1 where+  gfoldMap' _ _ = mempty+ instance GFoldable' U1 where   gfoldMap' _ U1 = mempty 
src/Generics/Deriving/Functor.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -13,6 +14,10 @@ {-# LANGUAGE PolyKinds #-} #endif +#if __GLASGOW_HASKELL__ >= 708+{-# LANGUAGE EmptyCase #-}+#endif+ module Generics.Deriving.Functor (   -- * Generic Functor class     GFunctor(..)@@ -59,6 +64,14 @@  class GFunctor' f where   gmap' :: (a -> b) -> f a -> f b++instance GFunctor' V1 where+  gmap' _ x = case x of+#if __GLASGOW_HASKELL__ >= 708+                {}+#else+                !_ -> error "Void gmap"+#endif  instance GFunctor' U1 where   gmap' _ U1 = U1
src/Generics/Deriving/Instances.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleInstances #-}@@ -422,13 +423,13 @@  instance Generic (V1 p) where     type Rep (V1 p) = Rep0V1 p-    from _ = M1 (error "No generic representation for empty datatype V1")-    to (M1 _) = error "No values for empty datatype V1"+    from x = M1 (case x of !_ -> error "No generic representation for empty datatype V1")+    to (M1 !_) = error "No values for empty datatype V1"  instance Generic1 V1 where     type Rep1 V1 = Rep1V1-    from1 _ = M1 (error "No generic representation for empty datatype V1")-    to1 (M1 _) = error "No values for empty datatype V1"+    from1 x = M1 (case x of !_ -> error "No generic representation for empty datatype V1")+    to1 (M1 !_) = error "No values for empty datatype V1"  data D1V1 
src/Generics/Deriving/Show.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -11,6 +12,10 @@ {-# LANGUAGE Trustworthy #-} #endif +#if __GLASGOW_HASKELL__ >= 708+{-# LANGUAGE EmptyCase #-}+#endif+ #if __GLASGOW_HASKELL__ < 709 {-# LANGUAGE OverlappingInstances #-} #endif@@ -88,6 +93,14 @@   gshowsPrec' :: Type -> Int -> f a -> ShowS   isNullary   :: f a -> Bool   isNullary = error "generic show (isNullary): unnecessary case"++instance GShow' V1 where+  gshowsPrec' _ _ x = case x of+#if __GLASGOW_HASKELL__ >= 708+                        {}+#else+                        !_ -> error "Void gshowsPrec"+#endif  instance GShow' U1 where   gshowsPrec' _ _ U1 = id
src/Generics/Deriving/TH.hs view
@@ -57,7 +57,6 @@     , deriveRepresentable1     , deriveRep0     , deriveRep1-    , simplInstance       -- * @make@- functions      -- $make@@ -83,6 +82,8 @@     , defaultRepOptions     , KindSigOptions     , defaultKindSigOptions+    , EmptyCaseOptions+    , defaultEmptyCaseOptions      -- ** Functions with optional arguments     , deriveAll0Options@@ -92,6 +93,11 @@     , deriveRepresentable1Options     , deriveRep0Options     , deriveRep1Options++    , makeFrom0Options+    , makeTo0Options+    , makeFrom1Options+    , makeTo1Options   ) where  import           Control.Monad ((>=>), unless, when)@@ -133,32 +139,56 @@   newtype Compose (f :: k2 -> *) (g :: k1 -> k2) (a :: k1) = Compose (f (g a))   $('deriveAll1Options' False ''Compose)   @--} --- | Given the names of a generic class, a type to instantiate, a function in--- the class and the default implementation, generates the code for a basic--- generic instance.-simplInstance :: Name -> Name -> Name -> Name -> Q [Dec]-simplInstance cl ty fn df = do-  x <- newName "x"-  let typ = ForallT [PlainTV x] []-        ((foldl (\a -> AppT a . VarT . tyVarBndrName) (ConT (genRepName Generic DataPlain ty)) []) `AppT` (VarT x))-  fmap (: []) $ instanceD (cxt []) (conT cl `appT` conT ty)-    [funD fn [clause [] (normalB (varE df `appE`-      (sigE (varE undefinedValName) (return typ)))) []]]+* 'EmptyCaseOptions': By default, all derived instances for empty data types+  (i.e., data types with no constructors) use 'error' in @from(1)@/@to(1)@.+  For instance, @data Empty@ would have this derived 'Generic' instance: +  @+  instance Generic Empty where+    type Rep Empty = D1 ('MetaData ...) V1+    from _ = M1 (error "No generic representation for empty datatype Empty")+    to (M1 _) = error "No generic representation for empty datatype Empty"+  @++  This matches the behavior of GHC up until 8.4, when derived @Generic(1)@+  instances began to use the @EmptyCase@ extension. In GHC 8.4, the derived+  'Generic' instance for @Empty@ would instead be:++  @+  instance Generic Empty where+    type Rep Empty = D1 ('MetaData ...) V1+    from x = M1 (case x of {})+    to (M1 x) = case x of {}+  @++  This is a slightly better encoding since, for example, any divergent+  computations passed to 'from' will actually diverge (as opposed to before,+  where the result would always be a call to 'error'). On the other hand, using+  this encoding in @generic-deriving@ has one large drawback: it requires+  enabling @EmptyCase@, an extension which was only introduced in GHC 7.8+  (and only received reliable pattern-match coverage checking in 8.2).++  The 'EmptyCaseOptions' field controls whether code should be emitted that+  uses @EmptyCase@ (i.e., 'EmptyCaseOptions' set to 'True') or not ('False').+  The default value is 'False'. Note that even if set to 'True', this option+  has no effect on GHCs before 7.8, as @EmptyCase@ did not exist then.+-}+ -- | Additional options for configuring derived 'Generic'/'Generic1' instances -- using Template Haskell. data Options = Options-  { repOptions     :: RepOptions-  , kindSigOptions :: KindSigOptions+  { repOptions       :: RepOptions+  , kindSigOptions   :: KindSigOptions+  , emptyCaseOptions :: EmptyCaseOptions   } deriving (Eq, Ord, Read, Show) --- | Sensible default 'Options' ('defaultRepOptions' and 'defaultKindSigOptions').+-- | Sensible default 'Options'. defaultOptions :: Options defaultOptions = Options-  { repOptions     = defaultRepOptions-  , kindSigOptions = defaultKindSigOptions+  { repOptions       = defaultRepOptions+  , kindSigOptions   = defaultKindSigOptions+  , emptyCaseOptions = defaultEmptyCaseOptions   }  -- | Configures whether 'Rep'/'Rep1' type instances should be defined inline in a@@ -180,6 +210,15 @@ defaultKindSigOptions :: KindSigOptions defaultKindSigOptions = True +-- | 'True' if generated code for empty data types should use the @EmptyCase@+-- extension, 'False' otherwise. This has no effect on GHCs before 7.8, since+-- @EmptyCase@ is only available in 7.8 or later.+type EmptyCaseOptions = Bool++-- | Sensible default 'EmptyCaseOptions'.+defaultEmptyCaseOptions :: EmptyCaseOptions+defaultEmptyCaseOptions = False+ -- | A backwards-compatible synonym for 'deriveAll0'. deriveAll :: Name -> Q [Dec] deriveAll = deriveAll0@@ -316,7 +355,8 @@ #else                          [origSigTy] tyInsRHS #endif-      mkBody maker = [clause [] (normalB $ mkCaseExp gClass name cons maker) []]+      ecOptions = emptyCaseOptions opts+      mkBody maker = [clause [] (normalB $ mkCaseExp gClass ecOptions name cons maker) []]       fcs = mkBody mkFrom       tcs = mkBody mkTo @@ -563,32 +603,48 @@  -- | Generates a lambda expression which behaves like 'from'. makeFrom0 :: Name -> Q Exp-makeFrom0 = makeFunCommon mkFrom Generic+makeFrom0 = makeFrom0Options defaultEmptyCaseOptions +-- | Like 'makeFrom0Options', but takes an 'EmptyCaseOptions' argument.+makeFrom0Options :: EmptyCaseOptions -> Name -> Q Exp+makeFrom0Options = makeFunCommon mkFrom Generic+ -- | A backwards-compatible synonym for 'makeTo0'. makeTo :: Name -> Q Exp makeTo = makeTo0  -- | Generates a lambda expression which behaves like 'to'. makeTo0 :: Name -> Q Exp-makeTo0 = makeFunCommon mkTo Generic+makeTo0 = makeTo0Options defaultEmptyCaseOptions +-- | Like 'makeTo0Options', but takes an 'EmptyCaseOptions' argument.+makeTo0Options :: EmptyCaseOptions -> Name -> Q Exp+makeTo0Options = makeFunCommon mkTo Generic+ -- | Generates a lambda expression which behaves like 'from1'. makeFrom1 :: Name -> Q Exp-makeFrom1 = makeFunCommon mkFrom Generic1+makeFrom1 = makeFrom1Options defaultEmptyCaseOptions +-- | Like 'makeFrom1Options', but takes an 'EmptyCaseOptions' argument.+makeFrom1Options :: EmptyCaseOptions -> Name -> Q Exp+makeFrom1Options = makeFunCommon mkFrom Generic1+ -- | Generates a lambda expression which behaves like 'to1'. makeTo1 :: Name -> Q Exp-makeTo1 = makeFunCommon mkTo Generic1+makeTo1 = makeTo1Options defaultEmptyCaseOptions -makeFunCommon :: (GenericClass -> Int -> Int -> Name -> [Con] -> Q Match)-              -> GenericClass -> Name -> Q Exp-makeFunCommon maker gClass n = do+-- | Like 'makeTo1Options', but takes an 'EmptyCaseOptions' argument.+makeTo1Options :: EmptyCaseOptions -> Name -> Q Exp+makeTo1Options = makeFunCommon mkTo Generic1++makeFunCommon :: (GenericClass -> EmptyCaseOptions ->  Int -> Int -> Name -> [Con] -> Q Match)+              -> GenericClass -> EmptyCaseOptions -> Name -> Q Exp+makeFunCommon maker gClass ecOptions n = do   i <- reifyDataInfo n   let (name, _, allTvbs, cons, dv) = either error id i   -- See Note [Forcing buildTypeInstance]   buildTypeInstance gClass False name allTvbs dv-    `seq` mkCaseExp gClass name cons maker+    `seq` mkCaseExp gClass ecOptions name cons maker  genRepName :: GenericClass -> DataVariety -> Name -> Name genRepName gClass dv n = mkName@@ -734,52 +790,72 @@     Just (boxTyName, _, _) -> conT boxTyName     Nothing                -> conT rec0TypeName `appT` return ty -mkCaseExp :: GenericClass -> Name -> [Con]-          -> (GenericClass -> Int -> Int -> Name -> [Con] -> Q Match)+mkCaseExp :: GenericClass -> EmptyCaseOptions -> Name -> [Con]+          -> (GenericClass -> EmptyCaseOptions -> Int -> Int -> Name -> [Con] -> Q Match)           -> Q Exp-mkCaseExp gClass dt cs matchmaker = do+mkCaseExp gClass ecOptions dt cs matchmaker = do   val <- newName "val"-  lam1E (varP val) $ caseE (varE val) [matchmaker gClass 1 0 dt cs]+  lam1E (varP val) $ caseE (varE val) [matchmaker gClass ecOptions 1 0 dt cs] -mkFrom :: GenericClass -> Int -> Int -> Name -> [Con] -> Q Match-mkFrom gClass m i dt cs = do+mkFrom :: GenericClass -> EmptyCaseOptions -> Int -> Int -> Name -> [Con] -> Q Match+mkFrom gClass ecOptions m i dt cs = do     y <- newName "y"     match (varP y)           (normalB $ conE m1DataName `appE` caseE (varE y) cases)           []   where     cases = case cs of-              [] -> [errorFrom dt]+              [] -> errorFrom ecOptions dt               _  -> zipWith (fromCon gClass wrapE (length cs)) [0..] cs     wrapE e = lrE m i e -errorFrom :: Name -> Q Match-errorFrom dt =-  match-    wildP-    (normalB $ varE errorValName `appE` stringE-      ("No generic representation for empty datatype " ++ nameBase dt))-    []--errorTo :: Name -> Q Match-errorTo dt =-  match-    wildP-    (normalB $ varE errorValName `appE` stringE-      ("No values for empty datatype " ++ nameBase dt))-    []+errorFrom :: EmptyCaseOptions -> Name -> [Q Match]+errorFrom useEmptyCase dt+  | useEmptyCase && ghc7'8OrLater+  = []+  | otherwise+  = [do z <- newName "z"+        match+          (varP z)+          (normalB $+            appE (varE seqValName) (varE z) `appE`+            appE (varE errorValName)+                 (stringE $ "No generic representation for empty datatype "+                          ++ nameBase dt))+          []] -mkTo :: GenericClass -> Int -> Int -> Name -> [Con] -> Q Match-mkTo gClass m i dt cs = do+mkTo :: GenericClass -> EmptyCaseOptions -> Int -> Int -> Name -> [Con] -> Q Match+mkTo gClass ecOptions m i dt cs = do     y <- newName "y"     match (conP m1DataName [varP y])           (normalB $ caseE (varE y) cases)           []   where     cases = case cs of-              [] -> [errorTo dt]+              [] -> errorTo ecOptions dt               _  -> zipWith (toCon gClass wrapP (length cs)) [0..] cs     wrapP p = lrP m i p++errorTo :: EmptyCaseOptions -> Name -> [Q Match]+errorTo useEmptyCase dt+  | useEmptyCase && ghc7'8OrLater+  = []+  | otherwise+  = [do z <- newName "z"+        match+          (varP z)+          (normalB $+            appE (varE seqValName) (varE z) `appE`+            appE (varE errorValName)+                 (stringE $ "No values for empty datatype " ++ nameBase dt))+          []]++ghc7'8OrLater :: Bool+#if __GLASGOW_HASKELL__ >= 708+ghc7'8OrLater = True+#else+ghc7'8OrLater = False+#endif  fromCon :: GenericClass -> (Q Exp -> Q Exp) -> Int -> Int -> Con -> Q Match fromCon _ wrap m i (NormalC cn []) =
src/Generics/Deriving/TH/Internal.hs view
@@ -769,6 +769,9 @@ mkGHCPrimName_tc :: String -> String -> Name mkGHCPrimName_tc = mkNameG_tc "ghc-prim" +mkGHCPrimName_v :: String -> String -> Name+mkGHCPrimName_v = mkNameG_v "ghc-prim"+ comp1DataName :: Name comp1DataName = mkGD4'4_d "Comp1" @@ -930,6 +933,9 @@  selNameValName :: Name selNameValName = mkGD4'4_v "selName"++seqValName :: Name+seqValName = mkGHCPrimName_v "GHC.Prim" "seq"  toValName :: Name toValName = mkGD4'4_v "to"
src/Generics/Deriving/Traversable.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -13,6 +14,10 @@ {-# LANGUAGE PolyKinds #-} #endif +#if __GLASGOW_HASKELL__ >= 708+{-# LANGUAGE EmptyCase #-}+#endif+ module Generics.Deriving.Traversable (   -- * Generic Traversable class     GTraversable(..)@@ -63,6 +68,14 @@  class GTraversable' t where   gtraverse' :: Applicative f => (a -> f b) -> t a -> f (t b)++instance GTraversable' V1 where+  gtraverse' _ x = pure $ case x of+#if __GLASGOW_HASKELL__ >= 708+                            {}+#else+                            !_ -> error "Void gtraverse"+#endif  instance GTraversable' U1 where   gtraverse' _ U1 = pure U1
+ tests/EmptyCaseSpec.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}++#if __GLASGOW_HASKELL__ >= 706+{-# LANGUAGE DataKinds #-}+#endif++#if __GLASGOW_HASKELL__ >= 708+{-# LANGUAGE EmptyCase #-}+#endif++module EmptyCaseSpec (main, spec) where++import Generics.Deriving.TH+import Test.Hspec++data Empty a+$(deriveAll0And1Options defaultOptions{emptyCaseOptions = True}+                        ''Empty)++main :: IO ()+main = hspec spec++spec :: Spec+spec = return ()