commit ghc-generics-sop for openSUSE:Factory
Hello community, here is the log from the commit of package ghc-generics-sop for openSUSE:Factory checked in at 2017-08-31 20:50:51 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-generics-sop (Old) and /work/SRC/openSUSE:Factory/.ghc-generics-sop.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "ghc-generics-sop" Thu Aug 31 20:50:51 2017 rev:9 rq:513247 version:0.3.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-generics-sop/ghc-generics-sop.changes 2017-06-04 01:53:23.878714201 +0200 +++ /work/SRC/openSUSE:Factory/.ghc-generics-sop.new/ghc-generics-sop.changes 2017-08-31 20:50:51.890601144 +0200 @@ -1,0 +2,5 @@ +Thu Jul 27 14:08:14 UTC 2017 - psimons@suse.com + +- Update to version 0.3.1.0. + +------------------------------------------------------------------- Old: ---- generics-sop-0.2.5.0.tar.gz New: ---- generics-sop-0.3.1.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-generics-sop.spec ++++++ --- /var/tmp/diff_new_pack.aplvdM/_old 2017-08-31 20:50:53.082433845 +0200 +++ /var/tmp/diff_new_pack.aplvdM/_new 2017-08-31 20:50:53.090432723 +0200 @@ -18,7 +18,7 @@ %global pkg_name generics-sop Name: ghc-%{pkg_name} -Version: 0.2.5.0 +Version: 0.3.1.0 Release: 0 Summary: Generic Programming using True Sums of Products License: BSD-3-Clause ++++++ generics-sop-0.2.5.0.tar.gz -> generics-sop-0.3.1.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/CHANGELOG.md new/generics-sop-0.3.1.0/CHANGELOG.md --- old/generics-sop-0.2.5.0/CHANGELOG.md 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/CHANGELOG.md 2017-06-11 15:25:51.000000000 +0200 @@ -1,3 +1,54 @@ +# 0.3.1.0 (2017-06-11) + +* Add AllZip, htrans, hcoerce, hfromI, htoI. + These functions are for converting between related + structures that do not have common signatures. + + The most common application of these functions seems + to be the scenario where a datatype has components + that are all wrapped in a common type constructor + application, e.g. a datatype where every component + is a `Maybe`. Then we can use `hfromI` after `from` + to turn the generically derived `SOP` of `I`s into + an `SOP` of `Maybe`s (and back). + +* Add `IsProductType`, `IsEnumType`, `IsWrappedType` + and `IsNewtype` constraint synonyms capturing + specific classes of datypes. + +# 0.3.0.0 (2017-04-29) + +* No longer compatible with GHC 7.6, due to the lack of + support for type-level literals. + +* Support type-level metadata. This is provided by the + `Generics.SOP.Type.Metadata` module. The two modules + `Generics.SOP.Metadata` and `Generics.SOP.Type.Metadata` + export nearly the same names, so for backwards compatibility, + we keep exporting `Generics.SOP.Metadata` directly from + `Generics.SOP`, whereas `Generics.SOP.Type.Metadata` is + supposed to be imported explicitly (and qualified). + + Term-level metadata is still available, but is now usually + computed automatically from the type-level metadata which + contains the same information, using the function + `demoteDatatypeInfo`. Term-level metadata is unchanged + from generics-sop-0.2, so in most cases, even if your + code makes use of metadata, you should not need to change + anything. + + If you use TH deriving, then both type-level metadata and + term-level metadata is generated for you automatically, + for all supported GHC versions. + + If you use GGP deriving, then type-level metadata is + available if you use GHC 8.0 or newer. If you use GHC 7.x, + then GHC.Generics supports only term-level metadata, so + we cannot translate that into type-level metadata. In + this combination, you cannot use code that relies on + type-level metadata, so you should either upgrade GHC or + switch to TH-based deriving. + # 0.2.5.0 (2017-04-21) * GHC 8.2 compatibility. @@ -79,8 +130,8 @@ hcliftA' p = hcliftA (allP p) where - allP :: proxy c -> Proxy (All c) - allP _ = Proxy + allP :: proxy c -> Proxy (All c) + allP _ = Proxy * Because `All` and `All2` are now type classes, they now have superclass constraints implying that the type-level lists they @@ -99,7 +150,7 @@ For one-dimensional type-level lists, replace - SingI xs => ... + SingI xs => ... by diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/generics-sop.cabal new/generics-sop-0.3.1.0/generics-sop.cabal --- old/generics-sop-0.2.5.0/generics-sop.cabal 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/generics-sop.cabal 2017-06-11 15:25:51.000000000 +0200 @@ -1,5 +1,5 @@ name: generics-sop -version: 0.2.5.0 +version: 0.3.1.0 synopsis: Generic Programming using True Sums of Products description: A library to support the definition of generic functions. @@ -37,7 +37,7 @@ build-type: Simple cabal-version: >=1.10 extra-source-files: CHANGELOG.md -tested-with: GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1, GHC == 8.0.2, GHC == 8.1.* +tested-with: GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1, GHC == 8.0.2, GHC == 8.1.* source-repository head type: git @@ -48,6 +48,7 @@ Generics.SOP.GGP Generics.SOP.TH Generics.SOP.Dict + Generics.SOP.Type.Metadata -- exposed via Generics.SOP: Generics.SOP.BasicFunctors Generics.SOP.Classes @@ -58,7 +59,7 @@ Generics.SOP.NS Generics.SOP.Universe Generics.SOP.Sing - build-depends: base >= 4.6 && < 5, + build-depends: base >= 4.7 && < 5, template-haskell >= 2.8 && < 2.13, ghc-prim >= 0.3 && < 0.6, deepseq >= 1.3 && < 1.5 @@ -100,9 +101,10 @@ if impl (ghc < 7.10) other-extensions: OverlappingInstances -test-suite generic-sop-examples +test-suite generics-sop-examples type: exitcode-stdio-1.0 main-is: Example.hs + other-modules: HTransExample hs-source-dirs: test default-language: Haskell2010 ghc-options: -Wall diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/src/Generics/SOP/Classes.hs new/generics-sop-0.3.1.0/src/Generics/SOP/Classes.hs --- old/generics-sop-0.2.5.0/src/Generics/SOP/Classes.hs 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/src/Generics/SOP/Classes.hs 2017-06-11 15:25:51.000000000 +0200 @@ -39,6 +39,7 @@ , fn_2 , fn_3 , fn_4 + , Same , Prod , HAp(..) -- ** Derived functions @@ -69,6 +70,10 @@ , HApInjs(..) -- * Expanding sums to products , HExpand(..) + -- * Transformation of index lists and coercions + , HTrans(..) + , hfromI + , htoI ) where #if !(MIN_VERSION_base(4,8,0)) @@ -147,6 +152,9 @@ fn_3 f = Fn $ \x -> Fn $ \x' -> Fn $ \x'' -> f x x' x'' fn_4 f = Fn $ \x -> Fn $ \x' -> Fn $ \x'' -> Fn $ \x''' -> f x x' x'' x''' +-- | Maps a structure to the same structure. +type family Same (h :: (k1 -> *) -> (l1 -> *)) :: (k2 -> *) -> (l2 -> *) + -- | Maps a structure containing sums to the corresponding -- product structure. type family Prod (h :: (k -> *) -> (l -> *)) :: (k -> *) -> (l -> *) @@ -519,5 +527,56 @@ -- hcexpand :: (AllN (Prod h) c xs) => proxy c -> (forall x . c x => f x) -> h f xs -> Prod h f xs +-- | A class for transforming structures into related structures with +-- a different index list, as long as the index lists have the same shape +-- and the elements and interpretation functions are suitably related. +-- +-- @since 0.3.1.0 +-- +class (Same h1 ~ h2, Same h2 ~ h1) => HTrans (h1 :: (k1 -> *) -> (l1 -> *)) (h2 :: (k2 -> *) -> (l2 -> *)) where + + -- | Transform a structure into a related structure given a conversion + -- function for the elements. + -- + -- @since 0.3.1.0 + -- + htrans :: + AllZipN (Prod h1) c xs ys + => proxy c + -> (forall x y . c x y => f x -> g y) + -> h1 f xs -> h2 g ys + + -- | Coerce a structure into a representationally equal structure. + -- + -- /Examples:/ + -- + -- >>> hcoerce (I (Just LT) :* I (Just 'x') :* I (Just True) :* Nil) :: NP Maybe '[Ordering, Char, Bool] + -- Just LT :* (Just 'x' :* (Just True :* Nil)) + -- >>> hcoerce (SOP (Z (K True :* K False :* Nil))) :: SOP I '[ '[Bool, Bool], '[Bool] ] + -- SOP (Z (I True :* (I False :* Nil))) + -- + -- @since 0.3.1.0 + hcoerce :: + (AllZipN (Prod h1) (LiftedCoercible f g) xs ys, HTrans h1 h2) + => h1 f xs -> h2 g ys + +-- | Specialization of 'hcoerce'. +-- +-- @since 0.3.1.0 +-- +hfromI :: + (AllZipN (Prod h1) (LiftedCoercible I f) xs ys, HTrans h1 h2) + => h1 I xs -> h2 f ys +hfromI = hcoerce + +-- | Specialization of 'hcoerce'. +-- +-- @since 0.3.1.0 +-- +htoI :: + (AllZipN (Prod h1) (LiftedCoercible f I) xs ys, HTrans h1 h2) + => h1 f xs -> h2 I ys +htoI = hcoerce + -- $setup -- >>> import Generics.SOP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/src/Generics/SOP/Constraint.hs new/generics-sop-0.3.1.0/src/Generics/SOP/Constraint.hs --- old/generics-sop-0.2.5.0/src/Generics/SOP/Constraint.hs 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/src/Generics/SOP/Constraint.hs 2017-06-11 15:25:51.000000000 +0200 @@ -17,7 +17,9 @@ , Constraint ) where +import Data.Coerce import GHC.Exts (Constraint) + import Generics.SOP.Sing -- | Require a constraint for every element of a list. @@ -46,9 +48,10 @@ -- | Type family used to implement 'All'. -- -type family AllF (c :: k -> Constraint) (xs :: [k]) :: Constraint -type instance AllF _c '[] = () -type instance AllF c (x ': xs) = (c x, All c xs) +type family + AllF (c :: k -> Constraint) (xs :: [k]) :: Constraint where + AllF _c '[] = () + AllF c (x ': xs) = (c x, All c xs) -- | Require a singleton for every inner list in a list of lists. type SListI2 = All SListI @@ -87,6 +90,83 @@ -- it triggers GHC's superclass cycle check when used in a -- class context. +-- | Require a constraint for pointwise for every pair of +-- elements from two lists. +-- +-- /Example:/ The constraint +-- +-- > All (~) '[ Int, Bool, Char ] '[ a, b, c ] +-- +-- is equivalent to the constraint +-- +-- > (Int ~ a, Bool ~ b, Char ~ c) +-- +-- @since 0.3.1.0 +-- +class + ( SListI xs, SListI ys + , SameShapeAs xs ys, SameShapeAs ys xs + , AllZipF c xs ys + ) => AllZip (c :: a -> b -> Constraint) (xs :: [a]) (ys :: [b]) +instance + ( SListI xs, SListI ys + , SameShapeAs xs ys, SameShapeAs ys xs + , AllZipF c xs ys + ) => AllZip c xs ys + +-- | Type family used to implement 'AllZip'. +-- +-- @since 0.3.1.0 +-- +type family + AllZipF (c :: a -> b -> Constraint) (xs :: [a]) (ys :: [b]) + :: Constraint where + AllZipF _c '[] '[] = () + AllZipF c (x ': xs) (y ': ys) = (c x y, AllZip c xs ys) + +-- | Type family that forces a type-level list to be of the same +-- shape as the given type-level list. +-- +-- The main use of this constraint is to help type inference to +-- learn something about otherwise unknown type-level lists. +-- +-- @since 0.3.1.0 +-- +type family + SameShapeAs (xs :: [a]) (ys :: [b]) :: Constraint where + SameShapeAs '[] ys = (ys ~ '[]) + SameShapeAs (x ': xs) ys = + (ys ~ (Head ys ': Tail ys), SameShapeAs xs (Tail ys)) + +-- | Utility function to compute the head of a type-level list. +-- +-- @since 0.3.1.0 +-- +type family Head (xs :: [a]) :: a where + Head (x ': xs) = x + +-- | Utility function to compute the tail of a type-level list. +-- +-- @since 0.3.1.0 +-- +type family Tail (xs :: [a]) :: [a] where + Tail (x ': xs) = xs + +-- | The constraint @LiftedCoercible f g x y@ is equivalent +-- to @Coercible (f x) (g y)@. +-- +-- @since 0.3.1.0 +-- +class Coercible (f x) (g y) => LiftedCoercible f g x y +instance Coercible (f x) (g y) => LiftedCoercible f g x y + +-- | Require a constraint for pointwise for every pair of +-- elements from two lists of lists. +-- +-- +class (AllZipF (AllZip f) xss yss, SListI xss, SListI yss, SameShapeAs xss yss, SameShapeAs yss xss) => AllZip2 f xss yss +instance (AllZipF (AllZip f) xss yss, SListI xss, SListI yss, SameShapeAs xss yss, SameShapeAs yss xss) => AllZip2 f xss yss + -- | Composition of constraints. -- -- Note that the result of the composition must be a constraint, @@ -126,6 +206,13 @@ -- type family AllN (h :: (k -> *) -> (l -> *)) (c :: k -> Constraint) :: l -> Constraint +-- | A generalization of 'AllZip' and 'AllZip2'. +-- +-- The family 'AllZipN' expands to 'AllZip' or 'AllZip2' depending on +-- whther the argument is indexed by a list or a list of lists. +-- +type family AllZipN (h :: (k -> *) -> (l -> *)) (c :: k1 -> k2 -> Constraint) :: l1 -> l2 -> Constraint + -- | A generalization of 'SListI'. -- -- The family 'SListIN' expands to 'SListI' or 'SListI2' depending diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/src/Generics/SOP/GGP.hs new/generics-sop-0.3.1.0/src/Generics/SOP/GGP.hs --- old/generics-sop-0.2.5.0/src/Generics/SOP/GGP.hs 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/src/Generics/SOP/GGP.hs 2017-06-11 15:25:51.000000000 +0200 @@ -1,4 +1,7 @@ -{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE PolyKinds, UndecidableInstances #-} +#if __GLASGOW_HASKELL__ >= 780 +{-# OPTIONS_GHC -fno-warn-unticked-promoted-constructors #-} +#endif -- | Derive @generics-sop@ boilerplate instances from GHC's 'GHC.Generic'. -- -- The technique being used here is described in the following paper: @@ -12,6 +15,9 @@ , GFrom , GTo , GDatatypeInfo +#if MIN_VERSION_base(4,9,0) + , GDatatypeInfoOf +#endif , gfrom , gto , gdatatypeInfo @@ -22,9 +28,16 @@ import Generics.SOP.NP as SOP import Generics.SOP.NS as SOP import Generics.SOP.BasicFunctors as SOP +#if !(MIN_VERSION_base(4,9,0)) import Generics.SOP.Constraint as SOP +#endif +#if MIN_VERSION_base(4,9,0) +import qualified Generics.SOP.Type.Metadata as SOP.T +#endif import Generics.SOP.Metadata as SOP +#if !(MIN_VERSION_base(4,9,0)) import Generics.SOP.Sing +#endif type family ToSingleCode (a :: * -> *) :: * type instance ToSingleCode (K1 _i a) = a @@ -46,6 +59,7 @@ data InfoProxy (c :: *) (f :: * -> *) (x :: *) = InfoProxy #endif +#if !(MIN_VERSION_base(4,9,0)) class GDatatypeInfo' (a :: * -> *) where gDatatypeInfo' :: proxy a -> DatatypeInfo (ToSumCode a '[]) @@ -105,6 +119,36 @@ where p :: InfoProxy c a x p = InfoProxy +#endif + +#if MIN_VERSION_base(4,9,0) +type family ToInfo (a :: * -> *) :: SOP.T.DatatypeInfo +type instance ToInfo (M1 D (MetaData n m p False) a) = + SOP.T.ADT m n (ToSumInfo a '[]) +type instance ToInfo (M1 D (MetaData n m p True) a) = + SOP.T.Newtype m n (ToSingleConstructorInfo a) + +type family ToSumInfo (a :: * -> *) (xs :: [SOP.T.ConstructorInfo]) :: [SOP.T.ConstructorInfo] +type instance ToSumInfo (a :+: b) xs = ToSumInfo a (ToSumInfo b xs) +type instance ToSumInfo V1 xs = xs +type instance ToSumInfo (M1 C c a) xs = ToSingleConstructorInfo (M1 C c a) ': xs + +type family ToSingleConstructorInfo (a :: * -> *) :: SOP.T.ConstructorInfo +type instance ToSingleConstructorInfo (M1 C (MetaCons n PrefixI False) a) = + SOP.T.Constructor n +type instance ToSingleConstructorInfo (M1 C (MetaCons n (InfixI assoc fix) False) a) = + SOP.T.Infix n assoc fix +type instance ToSingleConstructorInfo (M1 C (MetaCons n f True) a) = + SOP.T.Record n (ToProductInfo a '[]) + +type family ToProductInfo (a :: * -> *) (xs :: [SOP.T.FieldInfo]) :: [SOP.T.FieldInfo] +type instance ToProductInfo (a :*: b) xs = ToProductInfo a (ToProductInfo b xs) +type instance ToProductInfo U1 xs = xs +type instance ToProductInfo (M1 S c a) xs = ToSingleInfo (M1 S c a) ': xs + +type family ToSingleInfo (a :: * -> *) :: SOP.T.FieldInfo +type instance ToSingleInfo (M1 S (MetaSel (Just n) _su _ss _ds) a) = 'SOP.T.FieldInfo n +#endif class GFieldInfos (a :: * -> *) where gFieldInfos :: proxy a -> NP FieldInfo xs -> NP FieldInfo (ToProductCode a xs) @@ -209,7 +253,19 @@ type GTo a = GSumTo (GHC.Rep a) -- | Constraint for the class that computes 'gdatatypeInfo'. +#if MIN_VERSION_base(4,9,0) +type GDatatypeInfo a = SOP.T.DemoteDatatypeInfo (GDatatypeInfoOf a) (GCode a) +#else type GDatatypeInfo a = GDatatypeInfo' (GHC.Rep a) +#endif + +#if MIN_VERSION_base(4,9,0) +-- | Compute the datatype info of a datatype. +-- +-- @since 0.3.0.0 +-- +type GDatatypeInfoOf (a :: *) = ToInfo (GHC.Rep a) +#endif -- | An automatically computed version of 'Generics.SOP.from'. -- @@ -242,5 +298,9 @@ -- For more info, see 'Generics.SOP.HasDatatypeInfo'. -- gdatatypeInfo :: forall proxy a. (GDatatypeInfo a) => proxy a -> DatatypeInfo (GCode a) +#if MIN_VERSION_base(4,9,0) +gdatatypeInfo _ = SOP.T.demoteDatatypeInfo (Proxy :: Proxy (GDatatypeInfoOf a)) +#else gdatatypeInfo _ = gDatatypeInfo' (Proxy :: Proxy (GHC.Rep a)) +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/src/Generics/SOP/NP.hs new/generics-sop-0.3.1.0/src/Generics/SOP/NP.hs --- old/generics-sop-0.2.5.0/src/Generics/SOP/NP.hs 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/src/Generics/SOP/NP.hs 2017-06-11 15:25:51.000000000 +0200 @@ -64,12 +64,23 @@ , ccata_NP , ana_NP , cana_NP + -- * Transformation of index lists and coercions + , trans_NP + , trans_POP + , coerce_NP + , coerce_POP + , fromI_NP + , fromI_POP + , toI_NP + , toI_POP ) where #if !(MIN_VERSION_base(4,8,0)) import Control.Applicative #endif +import Data.Coerce import Data.Proxy (Proxy(..)) +import Unsafe.Coerce import Control.DeepSeq (NFData(..)) @@ -152,6 +163,9 @@ type instance AllN NP c = All c type instance AllN POP c = All2 c +type instance AllZipN NP c = AllZip c +type instance AllZipN POP c = AllZip2 c + type instance SListIN NP = SListI type instance SListIN POP = SListI2 @@ -266,6 +280,9 @@ _ap_POP_spec :: SListI xss => POP (f -.-> g) xss -> POP f xss -> POP g xss _ap_POP_spec (POP fs) (POP xs) = POP (liftA2_NP ap_NP fs xs) +type instance Same NP = NP +type instance Same POP = POP + type instance Prod NP = NP type instance Prod POP = POP @@ -602,3 +619,124 @@ go SNil _ = Nil go SCons s = case uncons s of (x, s') -> x :* go sList s' + +-- | Specialization of 'htrans'. +-- +-- @since 0.3.1.0 +-- +trans_NP :: + AllZip c xs ys + => proxy c + -> (forall x y . c x y => f x -> g y) + -> NP f xs -> NP g ys +trans_NP _ _t Nil = Nil +trans_NP p t (x :* xs) = t x :* trans_NP p t xs + +-- | Specialization of 'htrans'. +-- +-- @since 0.3.1.0 +-- +trans_POP :: + AllZip2 c xss yss + => proxy c + -> (forall x y . c x y => f x -> g y) + -> POP f xss -> POP g yss +trans_POP p t = + POP . trans_NP (allZipP p) (trans_NP p t) . unPOP + +allZipP :: proxy c -> Proxy (AllZip c) +allZipP _ = Proxy + +-- | Specialization of 'hcoerce'. +-- +-- @since 0.3.1.0 +-- +coerce_NP :: + forall f g xs ys . + AllZip (LiftedCoercible f g) xs ys + => NP f xs -> NP g ys +coerce_NP = + unsafeCoerce + +-- There is a bug in the way coerce works for higher-kinded +-- type variables that seems to occur only in GHC 7.10. +-- +-- Therefore, the safe versions of the coercion functions +-- are excluded below. This is harmless because they're only +-- present for documentation purposes and not exported. + +#if __GLASGOW_HASKELL__ < 710 || __GLASGOW_HASKELL__ >= 800 +_safe_coerce_NP :: + forall f g xs ys . + AllZip (LiftedCoercible f g) xs ys + => NP f xs -> NP g ys +_safe_coerce_NP = + trans_NP (Proxy :: Proxy (LiftedCoercible f g)) coerce +#endif + +-- | Specialization of 'hcoerce'. +-- +-- @since 0.3.1.0 +-- +coerce_POP :: + forall f g xss yss . + AllZip2 (LiftedCoercible f g) xss yss + => POP f xss -> POP g yss +coerce_POP = + unsafeCoerce + +#if __GLASGOW_HASKELL__ < 710 || __GLASGOW_HASKELL__ >= 800 +_safe_coerce_POP :: + forall f g xss yss . + AllZip2 (LiftedCoercible f g) xss yss + => POP f xss -> POP g yss +_safe_coerce_POP = + trans_POP (Proxy :: Proxy (LiftedCoercible f g)) coerce +#endif + +-- | Specialization of 'hfromI'. +-- +-- @since 0.3.1.0 +-- +fromI_NP :: + forall f xs ys . + AllZip (LiftedCoercible I f) xs ys + => NP I xs -> NP f ys +fromI_NP = hfromI + +-- | Specialization of 'htoI'. +-- +-- @since 0.3.1.0 +-- +toI_NP :: + forall f xs ys . + AllZip (LiftedCoercible f I) xs ys + => NP f xs -> NP I ys +toI_NP = htoI + +-- | Specialization of 'hfromI'. +-- +-- @since 0.3.1.0 +-- +fromI_POP :: + forall f xss yss . + AllZip2 (LiftedCoercible I f) xss yss + => POP I xss -> POP f yss +fromI_POP = hfromI + +-- | Specialization of 'htoI'. +-- +-- @since 0.3.1.0 +-- +toI_POP :: + forall f xss yss . + AllZip2 (LiftedCoercible f I) xss yss + => POP f xss -> POP I yss +toI_POP = htoI + +instance HTrans NP NP where + htrans = trans_NP + hcoerce = coerce_NP +instance HTrans POP POP where + htrans = trans_POP + hcoerce = coerce_POP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/src/Generics/SOP/NS.hs new/generics-sop-0.3.1.0/src/Generics/SOP/NS.hs --- old/generics-sop-0.2.5.0/src/Generics/SOP/NS.hs 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/src/Generics/SOP/NS.hs 2017-06-11 15:25:51.000000000 +0200 @@ -59,12 +59,23 @@ , cexpand_NS , expand_SOP , cexpand_SOP + -- * Transformation of index lists and coercions + , trans_NS + , trans_SOP + , coerce_NS + , coerce_SOP + , fromI_NS + , fromI_SOP + , toI_NS + , toI_SOP ) where #if !(MIN_VERSION_base(4,8,0)) import Control.Applicative #endif +import Data.Coerce import Data.Proxy +import Unsafe.Coerce import Control.DeepSeq (NFData(..)) @@ -342,6 +353,9 @@ _ap_SOP_spec :: SListI xss => POP (t -.-> f) xss -> SOP t xss -> SOP f xss _ap_SOP_spec (POP fs) (SOP xs) = SOP (liftA2_NS ap_NP fs xs) +type instance Same NS = NS +type instance Same SOP = SOP + type instance Prod NS = NP type instance Prod SOP = POP @@ -591,3 +605,125 @@ instance HExpand SOP where hexpand = expand_SOP hcexpand = cexpand_SOP + +-- | Specialization of 'htrans'. +-- +-- @since 0.3.1.0 +-- +trans_NS :: + AllZip c xs ys + => proxy c + -> (forall x y . c x y => f x -> g y) + -> NS f xs -> NS g ys +trans_NS _ t (Z x) = Z (t x) +trans_NS p t (S x) = S (trans_NS p t x) + +-- | Specialization of 'htrans'. +-- +-- @since 0.3.1.0 +-- +trans_SOP :: + AllZip2 c xss yss + => proxy c + -> (forall x y . c x y => f x -> g y) + -> SOP f xss -> SOP g yss +trans_SOP p t = + SOP . trans_NS (allZipP p) (trans_NP p t) . unSOP + +allZipP :: proxy c -> Proxy (AllZip c) +allZipP _ = Proxy + +-- | Specialization of 'hcoerce'. +-- +-- @since 0.3.1.0 +-- +coerce_NS :: + forall f g xs ys . + AllZip (LiftedCoercible f g) xs ys + => NS f xs -> NS g ys +coerce_NS = + unsafeCoerce + +-- There is a bug in the way coerce works for higher-kinded +-- type variables that seems to occur only in GHC 7.10. +-- +-- Therefore, the safe versions of the coercion functions +-- are excluded below. This is harmless because they're only +-- present for documentation purposes and not exported. + +#if __GLASGOW_HASKELL__ < 710 || __GLASGOW_HASKELL__ >= 800 +_safe_coerce_NS :: + forall f g xs ys . + AllZip (LiftedCoercible f g) xs ys + => NS f xs -> NS g ys +_safe_coerce_NS = + trans_NS (Proxy :: Proxy (LiftedCoercible f g)) coerce +#endif + +-- | Specialization of 'hcoerce'. +-- +-- @since 0.3.1.0 +-- +coerce_SOP :: + forall f g xss yss . + AllZip2 (LiftedCoercible f g) xss yss + => SOP f xss -> SOP g yss +coerce_SOP = + unsafeCoerce + +#if __GLASGOW_HASKELL__ < 710 || __GLASGOW_HASKELL__ >= 800 +_safe_coerce_SOP :: + forall f g xss yss . + AllZip2 (LiftedCoercible f g) xss yss + => SOP f xss -> SOP g yss +_safe_coerce_SOP = + trans_SOP (Proxy :: Proxy (LiftedCoercible f g)) coerce +#endif + +-- | Specialization of 'hfromI'. +-- +-- @since 0.3.1.0 +-- +fromI_NS :: + forall f xs ys . + AllZip (LiftedCoercible I f) xs ys + => NS I xs -> NS f ys +fromI_NS = hfromI + +-- | Specialization of 'htoI'. +-- +-- @since 0.3.1.0 +-- +toI_NS :: + forall f xs ys . + AllZip (LiftedCoercible f I) xs ys + => NS f xs -> NS I ys +toI_NS = htoI + +-- | Specialization of 'hfromI'. +-- +-- @since 0.3.1.0 +-- +fromI_SOP :: + forall f xss yss . + AllZip2 (LiftedCoercible I f) xss yss + => SOP I xss -> SOP f yss +fromI_SOP = hfromI + +-- | Specialization of 'htoI'. +-- +-- @since 0.3.1.0 +-- +toI_SOP :: + forall f xss yss . + AllZip2 (LiftedCoercible f I) xss yss + => SOP f xss -> SOP I yss +toI_SOP = htoI + +instance HTrans NS NS where + htrans = trans_NS + hcoerce = coerce_NS + +instance HTrans SOP SOP where + htrans = trans_SOP + hcoerce = coerce_SOP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/src/Generics/SOP/TH.hs new/generics-sop-0.3.1.0/src/Generics/SOP/TH.hs --- old/generics-sop-0.2.5.0/src/Generics/SOP/TH.hs 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/src/Generics/SOP/TH.hs 2017-06-11 15:25:51.000000000 +0200 @@ -5,15 +5,18 @@ , deriveGenericOnly , deriveGenericFunctions , deriveMetadataValue + , deriveMetadataType ) where import Control.Monad (replicateM) import Data.Maybe (fromMaybe) +import Data.Proxy import Language.Haskell.TH import Language.Haskell.TH.Syntax import Generics.SOP.BasicFunctors import qualified Generics.SOP.Metadata as SOP +import qualified Generics.SOP.Type.Metadata as SOP.T import Generics.SOP.NP import Generics.SOP.NS import Generics.SOP.Universe @@ -51,8 +54,12 @@ -- > to _ = error "unreachable" -- to avoid GHC warnings -- > -- > instance HasDatatypeInfo Tree where --- > datatypeInfo _ = ADT "Main" "Tree" --- > (Constructor "Leaf" :* Constructor "Node" :* Nil) +-- > type DatatypeInfoOf Tree = +-- > T.ADT "Main" "Tree" +-- > '[ T.Constructor "Leaf", T.Constructor "Node" ] +-- > +-- > datatypeInfo _ = +-- > T.demoteDatatypeInfo (Proxy :: Proxy (DatatypeInfoOf Tree)) -- -- /Limitations:/ Generation does not work for GADTs, for -- datatypes that involve existential quantification, for @@ -134,6 +141,29 @@ sequence [ sigD datatypeInfoName' [t| SOP.DatatypeInfo $(conT codeName') |] -- treeDatatypeInfo :: DatatypeInfo TreeCode , funD datatypeInfoName' [clause [] (normalB $ metadata' isNewtype name cons) []] -- treeDatatypeInfo = ... ] +{-# DEPRECATED deriveMetadataValue "Use 'deriveMetadataType' and 'demoteDatatypeInfo' instead." #-} + +-- | Derive @DatatypeInfo@ type for the type. +-- +-- /Example:/ If you say +-- +-- > deriveMetadataType ''Tree "TreeDatatypeInfo" +-- +-- then you get code that is equivalent to: +-- +-- > type TreeDatatypeInfo = +-- > T.ADT "Main" "Tree" +-- > [ T.Constructor "Leaf", T.Constructor "Node" ] +-- +-- @since 0.3.0.0 +-- +deriveMetadataType :: Name -> String -> Q [Dec] +deriveMetadataType n datatypeInfoName = do + let datatypeInfoName' = mkName datatypeInfoName + dec <- reifyDec n + withDataDec dec $ \ isNewtype _ctx name _bndrs cons _derivs -> + sequence + [ tySynD datatypeInfoName' [] (metadataType' isNewtype name cons) ] deriveGenericForDataDec :: Bool -> Cxt -> Name -> [TyVarBndr] -> [Con] -> Derivings -> Q [Dec] deriveGenericForDataDec _isNewtype _cxt name bndrs cons _derivs = do @@ -154,7 +184,14 @@ let typ = appTyVars name bndrs md <- instanceD (cxt []) [t| HasDatatypeInfo $typ |] - [metadata isNewtype name cons] + [ metadataType typ isNewtype name cons + , funD 'datatypeInfo + [ clause [wildP] + (normalB [| SOP.T.demoteDatatypeInfo (Proxy :: Proxy (DatatypeInfoOf $typ)) |]) + [] + ] + ] + -- [metadata isNewtype name cons] return [md] @@ -212,10 +249,11 @@ Compute metadata -------------------------------------------------------------------------------} -metadata :: Bool -> Name -> [Con] -> Q Dec -metadata isNewtype typeName cs = - funD 'datatypeInfo [clause [wildP] (normalB $ metadata' isNewtype typeName cs) []] +metadataType :: Q Type -> Bool -> Name -> [Con] -> Q Dec +metadataType typ isNewtype typeName cs = + tySynInstD ''DatatypeInfoOf (tySynEqn [typ] (metadataType' isNewtype typeName cs)) +-- | Derive term-level metadata. metadata' :: Bool -> Name -> [Con] -> Q Exp metadata' isNewtype typeName cs = md where @@ -263,6 +301,54 @@ mdAssociativity InfixR = [| SOP.RightAssociative |] mdAssociativity InfixN = [| SOP.NotAssociative |] +-- | Derive type-level metadata. +metadataType' :: Bool -> Name -> [Con] -> Q Type +metadataType' isNewtype typeName cs = md + where + md :: Q Type + md | isNewtype = [t| 'SOP.T.Newtype $(stringT (nameModule' typeName)) + $(stringT (nameBase typeName)) + $(mdCon (head cs)) + |] + | otherwise = [t| 'SOP.T.ADT $(stringT (nameModule' typeName)) + $(stringT (nameBase typeName)) + $(promotedTypeList $ map mdCon cs) + |] + + + mdCon :: Con -> Q Type + mdCon (NormalC n _) = [t| 'SOP.T.Constructor $(stringT (nameBase n)) |] + mdCon (RecC n ts) = [t| 'SOP.T.Record $(stringT (nameBase n)) + $(promotedTypeList (map mdField ts)) + |] + mdCon (InfixC _ n _) = do +#if MIN_VERSION_template_haskell(2,11,0) + fixity <- reifyFixity n + case fromMaybe defaultFixity fixity of + Fixity f a -> +#else + i <- reify n + case i of + DataConI _ _ _ (Fixity f a) -> +#endif + [t| 'SOP.T.Infix $(stringT (nameBase n)) $(mdAssociativity a) $(natT f) |] +#if !MIN_VERSION_template_haskell(2,11,0) + _ -> fail "Strange infix operator" +#endif + mdCon (ForallC _ _ _) = fail "Existentials not supported" +#if MIN_VERSION_template_haskell(2,11,0) + mdCon (GadtC _ _ _) = fail "GADTs not supported" + mdCon (RecGadtC _ _ _) = fail "GADTs not supported" +#endif + + mdField :: VarStrictType -> Q Type + mdField (n, _, _) = [t| 'SOP.T.FieldInfo $(stringT (nameBase n)) |] + + mdAssociativity :: FixityDirection -> Q Type + mdAssociativity InfixL = [t| 'SOP.T.LeftAssociative |] + mdAssociativity InfixR = [t| 'SOP.T.RightAssociative |] + mdAssociativity InfixN = [t| 'SOP.T.NotAssociative |] + nameModule' :: Name -> String nameModule' = fromMaybe "" . nameModule @@ -300,6 +386,12 @@ conInfo (RecGadtC _ _ _) = fail "GADTs not supported" #endif +stringT :: String -> Q Type +stringT = litT . strTyLit + +natT :: Int -> Q Type +natT = litT . numTyLit . fromIntegral + promotedTypeList :: [Q Type] -> Q Type promotedTypeList [] = promotedNilT promotedTypeList (t:ts) = [t| $promotedConsT $t $(promotedTypeList ts) |] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/src/Generics/SOP/Type/Metadata.hs new/generics-sop-0.3.1.0/src/Generics/SOP/Type/Metadata.hs --- old/generics-sop-0.2.5.0/src/Generics/SOP/Type/Metadata.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/generics-sop-0.3.1.0/src/Generics/SOP/Type/Metadata.hs 2017-06-11 15:25:51.000000000 +0200 @@ -0,0 +1,270 @@ +{-# LANGUAGE PolyKinds, UndecidableInstances #-} +-- | Type-level metadata +-- +-- This module provides datatypes (to be used promoted) that can represent the +-- metadata of Haskell datatypes on the type level. +-- +-- We do not reuse the term-level metadata types, because these are GADTs that +-- incorporate additional invariants. We could (at least in GHC 8) impose the +-- same invariants on the type level as well, but some tests have revealed that +-- the resulting type are rather inconvenient to work with. +-- +-- So we use simple datatypes to represent the type-level metadata, even if +-- this means that some invariants are not explicitly captured. +-- +-- We establish a relation between the term- and type-level versions of the +-- metadata by automatically computing the term-level version from the type-level +-- version. +-- +-- As we now have two versions of metadata (term-level and type-level) +-- with very similar, yet slightly different datatype definitions, the names +-- between the modules clash, and this module is recommended to be imported +-- qualified when needed. +-- +-- The interface exported by this module is still somewhat experimental. +-- +-- @since 0.3.0.0 +-- +module Generics.SOP.Type.Metadata + ( module Generics.SOP.Type.Metadata + -- * re-exports + , Associativity(..) + ) where + +import Data.Proxy +import GHC.Generics (Associativity(..)) +#if __GLASGOW_HASKELL__ >= 800 +import GHC.Types +#endif +import GHC.TypeLits + +import qualified Generics.SOP.Metadata as M +import Generics.SOP.NP +import Generics.SOP.Sing + +-- Regarding the CPP in the datatype definitions below: +-- +-- We cannot promote type synonyms in GHC 7, so we +-- use equivalent yet less descriptive definitions +-- for the older GHCs. + +-- | Metadata for a datatype (to be used promoted). +-- +-- A type of kind @'DatatypeInfo'@ contains meta-information about a datatype +-- that is not contained in its code. This information consists +-- primarily of the names of the datatype, its constructors, and possibly its +-- record selectors. +-- +-- The constructor indicates whether the datatype has been declared using @newtype@ +-- or not. +-- +-- @since 0.3.0.0 +-- +data DatatypeInfo = +#if __GLASGOW_HASKELL__ >= 800 + ADT ModuleName DatatypeName [ConstructorInfo] + -- ^ Standard algebraic datatype + | Newtype ModuleName DatatypeName ConstructorInfo + -- ^ Newtype +#else + ADT Symbol Symbol [ConstructorInfo] + -- ^ Standard algebraic datatype + | Newtype Symbol Symbol ConstructorInfo + -- ^ Newtype +#endif + +-- | Metadata for a single constructors (to be used promoted). +-- +-- @since 0.3.0.0 +-- +data ConstructorInfo = +#if __GLASGOW_HASKELL__ >= 800 + Constructor ConstructorName + -- ^ Normal constructor + | Infix ConstructorName Associativity Fixity + -- ^ Infix constructor + | Record ConstructorName [FieldInfo] + -- ^ Record constructor +#else + Constructor Symbol + -- ^ Normal constructor + | Infix Symbol Associativity Nat + -- ^ Infix constructor + | Record Symbol [FieldInfo] + -- ^ Record constructor +#endif + +-- | Metadata for a single record field (to be used promoted). +-- +-- @since 0.3.0.0 +-- +data FieldInfo = +#if __GLASGOW_HASKELL__ >= 800 + FieldInfo FieldName +#else + FieldInfo Symbol +#endif + +#if __GLASGOW_HASKELL__ >= 800 +-- | The name of a datatype. +type DatatypeName = Symbol + +-- | The name of a module. +type ModuleName = Symbol + +-- | The name of a data constructor. +type ConstructorName = Symbol + +-- | The name of a field / record selector. +type FieldName = Symbol + +-- | The fixity of an infix constructor. +type Fixity = Nat +#endif + +-- Demotion +-- +-- The following classes are concerned with computing the +-- term-level metadata from the type-level metadata. + +-- | Class for computing term-level datatype information from +-- type-level datatype information. +-- +-- @since 0.3.0.0 +-- +class DemoteDatatypeInfo (x :: DatatypeInfo) (xss :: [[*]]) where + -- | Given a proxy of some type-level datatype information, + -- return the corresponding term-level information. + -- + -- @since 0.3.0.0 + -- + demoteDatatypeInfo :: proxy x -> M.DatatypeInfo xss + +instance + (KnownSymbol m, KnownSymbol d, DemoteConstructorInfos cs xss) + => DemoteDatatypeInfo ('ADT m d cs) xss where + demoteDatatypeInfo _ = + M.ADT + (symbolVal (Proxy :: Proxy m)) + (symbolVal (Proxy :: Proxy d)) + (demoteConstructorInfos (Proxy :: Proxy cs)) + +instance + (KnownSymbol m, KnownSymbol d, DemoteConstructorInfo c '[ x ]) + => DemoteDatatypeInfo ('Newtype m d c) '[ '[ x ] ] where + demoteDatatypeInfo _ = + M.Newtype + (symbolVal (Proxy :: Proxy m)) + (symbolVal (Proxy :: Proxy d)) + (demoteConstructorInfo (Proxy :: Proxy c)) + +-- | Class for computing term-level constructor information from +-- type-level constructor information. +-- +-- @since 0.3.0.0 +-- +class DemoteConstructorInfos (cs :: [ConstructorInfo]) (xss :: [[*]]) where + -- | Given a proxy of some type-level constructor information, + -- return the corresponding term-level information as a product. + -- + -- @since 0.3.0.0 + -- + demoteConstructorInfos :: proxy cs -> NP M.ConstructorInfo xss + +instance DemoteConstructorInfos '[] '[] where + demoteConstructorInfos _ = Nil + +instance + (DemoteConstructorInfo c xs, DemoteConstructorInfos cs xss) + => DemoteConstructorInfos (c ': cs) (xs ': xss) where + demoteConstructorInfos _ = + demoteConstructorInfo (Proxy :: Proxy c) :* demoteConstructorInfos (Proxy :: Proxy cs) + +-- | Class for computing term-level constructor information from +-- type-level constructor information. +-- +-- @since 0.3.0.0 +-- +class DemoteConstructorInfo (x :: ConstructorInfo) (xs :: [*]) where + -- | Given a proxy of some type-level constructor information, + -- return the corresponding term-level information. + -- + -- @since 0.3.0.0 + -- + demoteConstructorInfo :: proxy x -> M.ConstructorInfo xs + +instance (KnownSymbol s, SListI xs) => DemoteConstructorInfo ('Constructor s) xs where + demoteConstructorInfo _ = M.Constructor (symbolVal (Proxy :: Proxy s)) + +instance + (KnownSymbol s, DemoteAssociativity a, KnownNat f) + => DemoteConstructorInfo ('Infix s a f) [y, z] where + demoteConstructorInfo _ = + M.Infix + (symbolVal (Proxy :: Proxy s)) + (demoteAssociativity (Proxy :: Proxy a)) + (fromInteger (natVal (Proxy :: Proxy f))) + +instance (KnownSymbol s, DemoteFieldInfos fs xs) => DemoteConstructorInfo ('Record s fs) xs where + demoteConstructorInfo _ = + M.Record (symbolVal (Proxy :: Proxy s)) (demoteFieldInfos (Proxy :: Proxy fs)) + +-- | Class for computing term-level field information from +-- type-level field information. +-- +-- @since 0.3.0.0 +-- +class SListI xs => DemoteFieldInfos (fs :: [FieldInfo]) (xs :: [*]) where + -- | Given a proxy of some type-level field information, + -- return the corresponding term-level information as a product. + -- + -- @since 0.3.0.0 + -- + demoteFieldInfos :: proxy fs -> NP M.FieldInfo xs + +instance DemoteFieldInfos '[] '[] where + demoteFieldInfos _ = Nil + +instance + (DemoteFieldInfo f x, DemoteFieldInfos fs xs) + => DemoteFieldInfos (f ': fs) (x ': xs) where + demoteFieldInfos _ = demoteFieldInfo (Proxy :: Proxy f) :* demoteFieldInfos (Proxy :: Proxy fs) + +-- | Class for computing term-level field information from +-- type-level field information. +-- +-- @since 0.3.0.0 +-- +class DemoteFieldInfo (x :: FieldInfo) (a :: *) where + -- | Given a proxy of some type-level field information, + -- return the corresponding term-level information. + -- + -- @since 0.3.0.0 + -- + demoteFieldInfo :: proxy x -> M.FieldInfo a + +instance KnownSymbol s => DemoteFieldInfo ('FieldInfo s) a where + demoteFieldInfo _ = M.FieldInfo (symbolVal (Proxy :: Proxy s)) + +-- | Class for computing term-level associativity information +-- from type-level associativity information. +-- +-- @since 0.3.0.0 +-- +class DemoteAssociativity (a :: Associativity) where + -- | Given a proxy of some type-level associativity information, + -- return the corresponding term-level information. + -- + -- @since 0.3.0.0 + -- + demoteAssociativity :: proxy a -> M.Associativity + +instance DemoteAssociativity 'LeftAssociative where + demoteAssociativity _ = M.LeftAssociative + +instance DemoteAssociativity 'RightAssociative where + demoteAssociativity _ = M.RightAssociative + +instance DemoteAssociativity 'NotAssociative where + demoteAssociativity _ = M.NotAssociative + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/src/Generics/SOP/Universe.hs new/generics-sop-0.3.1.0/src/Generics/SOP/Universe.hs --- old/generics-sop-0.2.5.0/src/Generics/SOP/Universe.hs 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/src/Generics/SOP/Universe.hs 2017-06-11 15:25:51.000000000 +0200 @@ -5,6 +5,7 @@ -- | Codes and interpretations module Generics.SOP.Universe where +import Data.Coerce (Coercible) import qualified GHC.Generics as GHC import Generics.SOP.BasicFunctors @@ -13,6 +14,7 @@ import Generics.SOP.Sing import Generics.SOP.GGP import Generics.SOP.Metadata +import qualified Generics.SOP.Type.Metadata as T -- | The (generic) representation of a datatype. -- @@ -137,7 +139,56 @@ -- of 'Generic' for the options. -- class HasDatatypeInfo a where + -- | Type-level datatype info + type DatatypeInfoOf a :: T.DatatypeInfo +#if MIN_VERSION_base(4,9,0) + type DatatypeInfoOf a = GDatatypeInfoOf a +#else + type DatatypeInfoOf a = DatatypeInfoOf a +#endif + + -- | Term-level datatype info; by default, the term-level datatype info is produced + -- from the type-level info. + -- datatypeInfo :: proxy a -> DatatypeInfo (Code a) - default datatypeInfo :: (GDatatypeInfo a, Code a ~ GCode a) - => proxy a -> DatatypeInfo (Code a) + default datatypeInfo :: (GDatatypeInfo a, GCode a ~ Code a) => proxy a -> DatatypeInfo (Code a) datatypeInfo = gdatatypeInfo + +-- | Constraint that captures that a datatype is a product type, +-- i.e., a type with a single constructor. +-- +-- It also gives access to the code for the arguments of that +-- constructor. +-- +-- @since 0.3.1.0 +-- +type IsProductType (a :: *) (xs :: [*]) = + (Generic a, Code a ~ '[ xs ]) + +-- | Constraint that captures that a datatype is an enumeration type, +-- i.e., none of the constructors have any arguments. +-- +-- @since 0.3.1.0 +-- +type IsEnumType (a :: *) = + (Generic a, All ((~) '[]) (Code a)) + +-- | Constraint that captures that a datatype is a single-constructor, +-- single-field datatype. This always holds for newtype-defined types, +-- but it can also be true for data-defined types. +-- +-- The constraint also gives access to the type that is wrapped. +-- +-- @since 0.3.1.0 +-- +type IsWrappedType (a :: *) (x :: *) = + (Generic a, Code a ~ '[ '[ x ] ]) + +-- | Constraint that captures that a datatype is a newtype. +-- This makes use of the fact that newtypes are always coercible +-- to the type they wrap, whereas datatypes are not. +-- +-- @since 0.3.1.0 +-- +type IsNewtype (a :: *) (x :: *) = + (IsWrappedType a x, Coercible a x) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/src/Generics/SOP.hs new/generics-sop-0.3.1.0/src/Generics/SOP.hs --- old/generics-sop-0.2.5.0/src/Generics/SOP.hs 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/src/Generics/SOP.hs 2017-06-11 15:25:51.000000000 +0200 @@ -218,6 +218,10 @@ -- * Codes and interpretations Generic(..) , Rep + , IsProductType + , IsEnumType + , IsWrappedType + , IsNewtype -- * n-ary datatypes , NP(..) , NS(..) @@ -296,6 +300,10 @@ , hsequenceK -- ** Expanding sums to products , HExpand(..) + -- ** Transformation of index lists and coercions + , HTrans(..) + , hfromI + , htoI -- ** Partial operations , fromList -- * Utilities @@ -322,10 +330,16 @@ -- ** Mapping constraints , All , All2 + , AllZip + , AllZip2 + , AllN + , AllZipN + -- ** Other constraints , Compose , And , Top - , AllN + , LiftedCoercible + , SameShapeAs -- ** Singletons , SList(..) , SListI(..) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/test/Example.hs new/generics-sop-0.3.1.0/test/Example.hs --- old/generics-sop-0.2.5.0/test/Example.hs 2017-04-21 15:30:39.000000000 +0200 +++ new/generics-sop-0.3.1.0/test/Example.hs 2017-06-11 15:25:51.000000000 +0200 @@ -10,6 +10,9 @@ import qualified GHC.Generics as GHC import Generics.SOP import Generics.SOP.TH +import qualified Generics.SOP.Type.Metadata as T + +import HTransExample -- Generic show, kind of gshow :: (Generic a, All2 Show (Code a)) => a -> String @@ -43,7 +46,7 @@ treeB :: TreeB treeB = NodeB (LeafB 1) (LeafB 2) -deriveGenericOnly ''TreeB +deriveGeneric ''TreeB instance Show TreeB where show = gshow @@ -56,6 +59,10 @@ deriveGenericFunctions ''TreeC "TreeCCode" "fromTreeC" "toTreeC" deriveMetadataValue ''TreeC "TreeCCode" "treeDatatypeInfo" +deriveMetadataType ''TreeC "TreeDatatypeInfo" + +demotedTreeDatatypeInfo :: DatatypeInfo TreeCCode +demotedTreeDatatypeInfo = T.demoteDatatypeInfo (Proxy :: Proxy TreeDatatypeInfo) instance Show TreeC where show x = gshowS (fromTreeC x) @@ -66,5 +73,9 @@ print tree print $ datatypeInfo (Proxy :: Proxy Tree) print treeB + print $ datatypeInfo (Proxy :: Proxy TreeB) print treeC print treeDatatypeInfo + print demotedTreeDatatypeInfo + print (treeDatatypeInfo == demotedTreeDatatypeInfo) + print $ convertFull tree diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/generics-sop-0.2.5.0/test/HTransExample.hs new/generics-sop-0.3.1.0/test/HTransExample.hs --- old/generics-sop-0.2.5.0/test/HTransExample.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/generics-sop-0.3.1.0/test/HTransExample.hs 2017-06-11 15:25:51.000000000 +0200 @@ -0,0 +1,27 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE DefaultSignatures #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE FunctionalDependencies #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE TypeFamilies #-} +module HTransExample where + +import Generics.SOP + +class IsTupleTypeOf xs y | xs -> y where + toTuple :: NP I xs -> y + default toTuple :: (Generic y, Code y ~ '[ xs ]) => NP I xs -> y + toTuple = to . SOP . Z + +instance IsTupleTypeOf '[] () +instance IsTupleTypeOf '[x1] x1 where toTuple = unI . hd +instance IsTupleTypeOf '[x1, x2] (x1, x2) +instance IsTupleTypeOf '[x1, x2, x3] (x1, x2, x3) +instance IsTupleTypeOf '[x1, x2, x3, x4] (x1, x2, x3, x4) + +convert :: (AllZip IsTupleTypeOf xss ys) => NS (NP I) xss -> NS I ys +convert = htrans (Proxy :: Proxy IsTupleTypeOf) (I . toTuple) + +convertFull :: (Generic a, AllZip IsTupleTypeOf (Code a) ys) => a -> NS I ys +convertFull = convert . unSOP . from
participants (1)
-
root@hilbert.suse.de