generic-data 0.6.0.1 → 0.7.0.0
raw patch · 9 files changed
+84/−28 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Generic.Data.Internal.Generically: instance (GHC.Generics.Generic a, GHC.Base.Monoid (GHC.Generics.Rep a ())) => GHC.Base.Monoid (Generic.Data.Internal.Generically.Generically a)
+ Generic.Data: gcoerce :: (Generic a, Generic b, Coercible (Rep a) (Rep b)) => a -> b
+ Generic.Data: gcoerceBinop :: (Generic a, Generic b, Coercible (Rep a) (Rep b)) => (a -> a -> a) -> b -> b -> b
+ Generic.Data.Internal.Generically: instance (GHC.Base.Semigroup a, GHC.Generics.Generic a, GHC.Base.Monoid (GHC.Generics.Rep a ())) => GHC.Base.Monoid (Generic.Data.Internal.Generically.Generically a)
+ Generic.Data.Internal.Utils: coerce1 :: Coercible f g => f x -> g x
+ Generic.Data.Internal.Utils: gcoerce :: (Generic a, Generic b, Coercible (Rep a) (Rep b)) => a -> b
+ Generic.Data.Internal.Utils: gcoerceBinop :: (Generic a, Generic b, Coercible (Rep a) (Rep b)) => (a -> a -> a) -> b -> b -> b
Files
- CHANGELOG.md +6/−0
- README.md +39/−17
- generic-data.cabal +1/−1
- src/Generic/Data.hs +5/−0
- src/Generic/Data/Internal/Data.hs +2/−2
- src/Generic/Data/Internal/Generically.hs +5/−2
- src/Generic/Data/Internal/Microsurgery.hs +6/−6
- src/Generic/Data/Internal/Utils.hs +17/−0
- test/unit.hs +3/−0
CHANGELOG.md view
@@ -1,3 +1,9 @@+# 0.7.0.0++- Changed `Monoid` instance for `Generically`, to be compatible with users'+ non-generic instances of `Semigroup`. Thanks to yairchu.+- Add `gcoerce`, `gcoerceBinop`.+ # 0.6.0.1 - Fix derivation of `Show1` for `(:.:)`
README.md view
@@ -4,7 +4,34 @@ ## Generic deriving for standard classes +### Example: generically deriving Semigroup instances for products++Semi-automatic method using `gmappend`+ ```haskell+data Foo a = Bar [a] [a] deriving Generic++instance Semigroup (Foo a) where+ (<>) = gmappend+```++This library also synergizes with the `DerivingVia` extension+(introduced in GHC 8.6), thanks to the `Generically` newtype.++```haskell+data Foo a = Bar [a] [a]+ deriving Generic+ deriving Semigroup via (Generically (Foo a))+```++These examples can be found in `test/example.hs`.++---++Note for completeness, the first example uses the following extensions and+imports:++```haskell {-# LANGUAGE DeriveGeneric #-} -- base@@ -12,35 +39,32 @@ import GHC.Generics -- generic-data-import Generic.Data (gmappend, Generically(..))+import Generic.Data (gmappend) import Generic.Data.Orphans ()--data Foo a = Bar [a] [a] deriving Generic--instance Semigroup (Foo a) where- (<>) = gmappend+``` --- also with some additional extensions --+The second example makes these additions on top: +```haskell {-# LANGUAGE DerivingStrategies, DerivingVia #-} -- since GHC 8.6.1 -data Foo a = Bar [a] [a]- deriving Generic- deriving Semigroup via (Generically (Foo a))---- This example can be found in test/example.hs+-- In addition to the previous imports+import Generic.Data (Generically(..)) ``` +### Supported classes+ Supported classes that GHC currently can't derive: `Semigroup`, `Monoid`, `Applicative`, `Alternative`, `Eq1`, `Ord1`, `Show1`. Other classes from base are also supported, even though GHC can already derive them: -- `Eq`, `Ord`, `Enum`, `Bounded`, `Show` (standard);-- `Functor`, `Foldable`, `Traversable` (via extensions, `DeriveFunctor`, etc.).+- `Eq`, `Ord`, `Enum`, `Bounded`, `Show` (derivable by the standard);+- `Functor`, `Foldable`, `Traversable` (derivable via extensions,+ `DeriveFunctor`, etc.). (`Read` is currently not implemented.) @@ -75,12 +99,11 @@ ```haskell {-# LANGUAGE DeriveGeneric #-}- import GHC.Generic (Generic)- import Generic.Data (gshowsPrec) import Generic.Data.Microsurgery (toData, derecordify) +-- An example record type newtype T = T { unT :: Int } deriving Generic -- Naively deriving Show would result in this being shown:@@ -102,7 +125,6 @@ ```haskell {-# LANGUAGE DeriveGeneric, DerivingVia #-}- import GHC.Generic (Generic) -- Constructors must be visible to use DerivingVia
generic-data.cabal view
@@ -1,5 +1,5 @@ name: generic-data-version: 0.6.0.1+version: 0.7.0.0 synopsis: Deriving instances with GHC.Generics and related utilities description: Generic implementations of standard type classes.
src/Generic/Data.hs view
@@ -113,6 +113,10 @@ , pack , unpack + -- * Generic coercions+ , gcoerce+ , gcoerceBinop+ -- * Accessing metadata -- | Using @TypeApplications@.@@ -163,3 +167,4 @@ import Generic.Data.Internal.Show import Generic.Data.Internal.Newtype import Generic.Data.Internal.Resolvers+import Generic.Data.Internal.Utils
src/Generic/Data/Internal/Data.hs view
@@ -31,11 +31,11 @@ , Eq, Ord, Eq1, Ord1, Semigroup, Monoid ) -- | Conversion between a generic type and the synthetic type made using its--- representation.+-- representation. Inverse of 'fromData'. toData :: Generic a => a -> Data (Rep a) p toData = Data . from --- | Inverse of 'fromData'.+-- | Inverse of 'toData'. fromData :: Generic a => Data (Rep a) p -> a fromData = to . unData
src/Generic/Data/Internal/Generically.hs view
@@ -36,9 +36,12 @@ instance (Generic a, Semigroup (Rep a ())) => Semigroup (Generically a) where (<>) = gmappend -instance (Generic a, Monoid (Rep a ())) => Monoid (Generically a) where+-- | This uses the 'Semigroup' instance of the wrapped type 'a' to define 'mappend'.+-- The purpose of this instance is to derive 'mempty', while remaining consistent+-- with possibly custom 'Semigroup' instances.+instance (Semigroup a, Generic a, Monoid (Rep a ())) => Monoid (Generically a) where mempty = gmempty- mappend = gmappend'+ mappend (Generically x) (Generically y) = Generically (x <> y) instance (Generic a, GEnum StandardEnum (Rep a)) => Enum (Generically a) where toEnum = gtoEnum
src/Generic/Data/Internal/Microsurgery.hs view
@@ -42,7 +42,7 @@ -- @ type Surgery (s :: *) (a :: *) = Generically (Surgery' s a) --- | See 'Surgery''.+-- | See 'Surgery'. newtype Surgery' (s :: *) (a :: *) = Surgery' { unSurgery' :: a } instance (Generic a, Coercible (GSurgery s (Rep a)) (Rep a)) => Generic (Surgery' s a) where@@ -78,7 +78,7 @@ -- Concretely, set the last field of 'MetaCons' to 'False' and forget field -- names. ----- This is a defunctionalized symbol, to be applied using 'GSurgery'.+-- This is a defunctionalized symbol, applied using 'GSurgery' or 'Surgery'. data Derecordify :: * type instance GSurgery Derecordify f = GDerecordify f @@ -112,7 +112,7 @@ -- > -- > data Foo = Bar Baz ----- This is a defunctionalized symbol, to be applied using 'GSurgery'.+-- This is a defunctionalized symbol, applied using 'GSurgery' or 'Surgery'. data Typeage :: * type instance GSurgery Typeage (M1 D ('MetaData nm md pk _nt) f) = M1 D ('MetaData nm md pk 'False) f @@ -150,7 +150,7 @@ -- > -- > data Foo = Bar { bag :: Zap } ----- This is a defunctionalized symbol, to be applied using 'GSurgery'.+-- This is a defunctionalized symbol, applied using 'GSurgery' or 'Surgery'. data RenameFields (rnm :: *) :: * type instance GSurgery (RenameFields rnm) f = GRenameFields rnm f @@ -171,7 +171,7 @@ -- > -- > data Foo = Car { baz :: Zap } ----- This is a defunctionalized symbol, to be applied using 'GSurgery'.+-- This is a defunctionalized symbol, applied using 'GSurgery' or 'Surgery'. data RenameConstrs (rnm :: *) :: * type instance GSurgery (RenameConstrs rnm) f = GRenameConstrs rnm f @@ -252,7 +252,7 @@ -- | Apply a type constructor @f@ to every field type of a generic -- representation @r@. ----- This is a defunctionalized symbol, to be applied using 'GSurgery'.+-- This is a defunctionalized symbol, applied using 'GSurgery' or 'Surgery'. data OnFields (f :: * -> *) :: * type instance GSurgery (OnFields f) g = GOnFields f g
src/Generic/Data/Internal/Utils.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE BangPatterns,+ FlexibleContexts, PolyKinds #-} module Generic.Data.Internal.Utils where@@ -7,9 +8,25 @@ import Data.Coerce import GHC.Generics +-- | Convert between types with representationally equivalent generic+-- representations.+gcoerce+ :: (Generic a, Generic b, Coercible (Rep a) (Rep b))+ => a -> b+gcoerce = to . coerce1 . from++-- | Compose 'gcoerce' with a binary operation.+gcoerceBinop+ :: (Generic a, Generic b, Coercible (Rep a) (Rep b))+ => (a -> a -> a) -> (b -> b -> b)+gcoerceBinop f x y = gcoerce (f (gcoerce x) (gcoerce y))+ -- | Coerce while preserving the type index. coerce' :: Coercible (f x) (g x) => f x -> g x coerce' = coerce++coerce1 :: Coercible f g => f x -> g x+coerce1 = coerce -- | Elimination of @V1@. absurd1 :: V1 x -> a
test/unit.hs view
@@ -16,6 +16,9 @@ data P a = P a a deriving (Generic, Generic1) +instance Semigroup a => Semigroup (P a) where+ x <> y = unGenerically (Generically x <> Generically y)+ type PTy a = a -> a -> Generically (P a) p :: PTy a