packages feed

generic-data 0.8.2.0 → 0.8.3.0

raw patch · 10 files changed

+371/−16 lines, 10 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Generic.Data.Internal.Show: isSymDataCon :: String -> Bool
- Generic.Data.Internal.Show: isSymVar :: String -> Bool
+ Generic.Data: gliftReadPrec :: (Generic1 f, GRead1 (Rep1 f)) => ReadPrec a -> ReadPrec [a] -> ReadPrec (f a)
+ Generic.Data: greadPrec :: (Generic a, GRead0 (Rep a)) => ReadPrec a
+ Generic.Data: type GRead0 = GRead Proxy
+ Generic.Data: type GRead1 = GRead Identity
+ Generic.Data.Internal.Generically: instance (GHC.Generics.Generic a, Generic.Data.Internal.Read.GRead0 (GHC.Generics.Rep a)) => GHC.Read.Read (Generic.Data.Internal.Generically.Generically a)
+ Generic.Data.Internal.Generically: instance (GHC.Generics.Generic1 f, Generic.Data.Internal.Read.GRead1 (GHC.Generics.Rep1 f)) => Data.Functor.Classes.Read1 (Generic.Data.Internal.Generically.Generically1 f)
+ Generic.Data.Internal.Generically: instance (GHC.Generics.Generic1 f, Generic.Data.Internal.Read.GRead1 (GHC.Generics.Rep1 f), GHC.Read.Read a) => GHC.Read.Read (Generic.Data.Internal.Generically.Generically1 f a)
+ Generic.Data.Internal.Read: [Branch] :: ReadPrecTree (f a) -> ReadPrecTree (g a) -> ReadPrecTree ((f :*: g) a)
+ Generic.Data.Internal.Read: [M1Leaf] :: ReadPrec (f a) -> ReadPrecTree (M1 i c f a)
+ Generic.Data.Internal.Read: [U1Leaf] :: ReadPrecTree (U1 a)
+ Generic.Data.Internal.Read: class GRead p f
+ Generic.Data.Internal.Read: class GReadC p c f
+ Generic.Data.Internal.Read: class GReadFields p f
+ Generic.Data.Internal.Read: class GReadNamed p f
+ Generic.Data.Internal.Read: class GReadSingle p f
+ Generic.Data.Internal.Read: class IsNullaryDataType f
+ Generic.Data.Internal.Read: coerceM1 :: ReadPrec (f p) -> ReadPrec (M1 i c f p)
+ Generic.Data.Internal.Read: data ReadPrecTree a
+ Generic.Data.Internal.Read: gPrecRead :: GRead p f => p (ReadPrec a, ReadPrec [a]) -> ReadPrec (f a)
+ Generic.Data.Internal.Read: gPrecReadC :: GReadC p c f => p (ReadPrec a, ReadPrec [a]) -> String -> Fixity -> ReadPrec (M1 C c f a)
+ Generic.Data.Internal.Read: gPrecReadFields :: GReadFields p f => p (ReadPrec a, ReadPrec [a]) -> ReadPrecTree (f a)
+ Generic.Data.Internal.Read: gPrecReadNamed :: GReadNamed p f => p (ReadPrec a, ReadPrec [a]) -> ReadPrec (f a)
+ Generic.Data.Internal.Read: gPrecReadSingle :: GReadSingle p f => p (ReadPrec a, ReadPrec [a]) -> ReadPrec (f a)
+ Generic.Data.Internal.Read: gliftReadPrec :: (Generic1 f, GRead1 (Rep1 f)) => ReadPrec a -> ReadPrec [a] -> ReadPrec (f a)
+ Generic.Data.Internal.Read: greadPrec :: (Generic a, GRead0 (Rep a)) => ReadPrec a
+ Generic.Data.Internal.Read: identHLexemes :: String -> [Lexeme]
+ Generic.Data.Internal.Read: instance (Data.Functor.Classes.Read1 f, Generic.Data.Internal.Read.GReadSingle p g) => Generic.Data.Internal.Read.GReadSingle p (f GHC.Generics.:.: g)
+ Generic.Data.Internal.Read: instance (GHC.Generics.Constructor c, Generic.Data.Internal.Read.GReadC p c f) => Generic.Data.Internal.Read.GRead p (GHC.Generics.M1 GHC.Generics.C c f)
+ Generic.Data.Internal.Read: instance (GHC.Generics.Selector c, Generic.Data.Internal.Read.GReadSingle p f) => Generic.Data.Internal.Read.GReadNamed p (GHC.Generics.M1 GHC.Generics.S c f)
+ Generic.Data.Internal.Read: instance (Generic.Data.Internal.Read.GRead p f, Generic.Data.Internal.Read.GRead p g) => Generic.Data.Internal.Read.GRead p (f GHC.Generics.:+: g)
+ Generic.Data.Internal.Read: instance (Generic.Data.Internal.Read.GRead p f, Generic.Data.Internal.Read.IsNullaryDataType f) => Generic.Data.Internal.Read.GRead p (GHC.Generics.M1 GHC.Generics.D d f)
+ Generic.Data.Internal.Read: instance (Generic.Data.Internal.Read.GReadFields p f, Generic.Data.Internal.Read.GReadFields p g) => Generic.Data.Internal.Read.GReadFields p (f GHC.Generics.:*: g)
+ Generic.Data.Internal.Read: instance (Generic.Data.Internal.Read.GReadNamed p f, Generic.Data.Internal.Read.GReadNamed p g) => Generic.Data.Internal.Read.GReadNamed p (f GHC.Generics.:*: g)
+ Generic.Data.Internal.Read: instance Data.Functor.Classes.Read1 f => Generic.Data.Internal.Read.GReadSingle Data.Functor.Identity.Identity (GHC.Generics.Rec1 f)
+ Generic.Data.Internal.Read: instance GHC.Read.Read a => Generic.Data.Internal.Read.GReadSingle p (GHC.Generics.K1 i a)
+ Generic.Data.Internal.Read: instance Generic.Data.Internal.Read.GRead p GHC.Generics.V1
+ Generic.Data.Internal.Read: instance Generic.Data.Internal.Read.GReadFields p GHC.Generics.U1
+ Generic.Data.Internal.Read: instance Generic.Data.Internal.Read.GReadFields p f => Generic.Data.Internal.Read.GReadC p ('GHC.Generics.MetaCons s y 'GHC.Types.False) f
+ Generic.Data.Internal.Read: instance Generic.Data.Internal.Read.GReadNamed p GHC.Generics.U1
+ Generic.Data.Internal.Read: instance Generic.Data.Internal.Read.GReadNamed p f => Generic.Data.Internal.Read.GReadC p ('GHC.Generics.MetaCons s y 'GHC.Types.True) f
+ Generic.Data.Internal.Read: instance Generic.Data.Internal.Read.GReadSingle Data.Functor.Identity.Identity GHC.Generics.Par1
+ Generic.Data.Internal.Read: instance Generic.Data.Internal.Read.GReadSingle p f => Generic.Data.Internal.Read.GReadFields p (GHC.Generics.M1 GHC.Generics.S c f)
+ Generic.Data.Internal.Read: instance Generic.Data.Internal.Read.IsNullaryDataType (GHC.Generics.C1 c f)
+ Generic.Data.Internal.Read: instance Generic.Data.Internal.Read.IsNullaryDataType (f GHC.Generics.:+: g)
+ Generic.Data.Internal.Read: instance Generic.Data.Internal.Read.IsNullaryDataType GHC.Generics.V1
+ Generic.Data.Internal.Read: isNullaryDataType :: IsNullaryDataType f => f a -> Bool
+ Generic.Data.Internal.Read: liftReadPrecCompat :: Read1 f => (ReadPrec a, ReadPrec [a]) -> ReadPrec (f a)
+ Generic.Data.Internal.Read: readPrefixCon :: String -> ReadPrec ()
+ Generic.Data.Internal.Read: readSurround :: Char -> ReadPrec a -> Char -> ReadPrec a
+ Generic.Data.Internal.Read: snocView :: [a] -> Maybe ([a], a)
+ Generic.Data.Internal.Read: toReadPrec :: ReadPrecTree a -> ReadPrec a
+ Generic.Data.Internal.Read: type GRead0 = GRead Proxy
+ Generic.Data.Internal.Read: type GRead1 = GRead Identity
+ Generic.Data.Internal.Utils: isSymDataCon :: String -> Bool
+ Generic.Data.Internal.Utils: isSymVar :: String -> Bool

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+# 0.8.3.0++- Add generic `Read`. Thanks to RyanGlScott.+ # 0.8.2.0  - Add microsurgery `CopyRep`.
README.md view
@@ -62,11 +62,9 @@ Other classes from base are also supported, even though GHC can already derive them: -- `Eq`, `Ord`, `Enum`, `Bounded`, `Show` (derivable by the standard);+- `Eq`, `Ord`, `Enum`, `Bounded`, `Show`, `Read` (derivable by the standard); - `Functor`, `Foldable`, `Traversable` (derivable via extensions,   `DeriveFunctor`, etc.).--(`Read` is currently not implemented.)  To derive type classes outside of the standard library, it might be worth taking a look at [one-liner](https://hackage.haskell.org/package/one-liner).
generic-data.cabal view
@@ -1,5 +1,5 @@ name:                generic-data-version:             0.8.2.0+version:             0.8.3.0 synopsis:            Deriving instances with GHC.Generics and related utilities description:   Generic implementations of standard type classes.@@ -10,8 +10,8 @@ license-file:        LICENSE author:              Li-yao Xia maintainer:          lysxia@gmail.com-copyright:           2018 Li-yao Xia-category:            Other+copyright:           2018-2020 Li-yao Xia+category:            Generics build-type:          Simple extra-source-files:  README.md, CHANGELOG.md cabal-version:       >=1.10@@ -34,6 +34,7 @@     Generic.Data.Internal.Microsurgery     Generic.Data.Internal.Newtype     Generic.Data.Internal.Prelude+    Generic.Data.Internal.Read     Generic.Data.Internal.Resolvers     Generic.Data.Internal.Show     Generic.Data.Internal.Utils
src/Generic/Data.hs view
@@ -30,6 +30,11 @@     -- | Can also be derived by GHC as part of the standard.   , gcompare +    -- ** 'Read'+    -- | Can also be derived by GHC as part of the standard.+  , greadPrec+  , GRead0+     -- ** 'Show'     -- | Can also be derived by GHC as part of the standard.   , gshowsPrec@@ -101,6 +106,10 @@     -- ** 'Data.Functor.Classes.Ord1'   , gliftCompare +    -- ** 'Data.Functor.Classes.Read1'+  , gliftReadPrec+  , GRead1+     -- ** 'Data.Functor.Classes.Show1'   , gliftShowsPrec   , GShow1@@ -176,6 +185,7 @@ import Generic.Data.Internal.Enum import Generic.Data.Internal.Generically import Generic.Data.Internal.Meta+import Generic.Data.Internal.Read import Generic.Data.Internal.Show import Generic.Data.Internal.Newtype import Generic.Data.Internal.Resolvers
src/Generic/Data/Internal/Generically.hs view
@@ -20,10 +20,12 @@ import Data.Semigroup import Data.Ix import GHC.Generics+import Text.Read  import Generic.Data.Internal.Prelude import Generic.Data.Internal.Enum import Generic.Data.Internal.Error+import Generic.Data.Internal.Read import Generic.Data.Internal.Show  -- | Type with instances derived via 'Generic'.@@ -40,6 +42,10 @@ instance (Generic a, Ord (Rep a ())) => Ord (Generically a) where   compare = gcompare +instance (Generic a, GRead0 (Rep a)) => Read (Generically a) where+  readPrec = greadPrec+  readListPrec = readListPrecDefault+ instance (Generic a, GShow0 (Rep a)) => Show (Generically a) where   showsPrec = gshowsPrec @@ -110,6 +116,23 @@  instance (Generic1 f, Ord1 (Rep1 f), Ord a) => Ord (Generically1 f a) where   compare = compare1++instance (Generic1 f, GRead1 (Rep1 f)) => Read1 (Generically1 f) where+#if MIN_VERSION_base(4,10,0)+  liftReadPrec = gliftReadPrec+  liftReadListPrec = liftReadListPrecDefault+#else+  liftReadsPrec rp rl = readPrec_to_S $+    gliftReadPrec (readS_to_Prec rp) (readS_to_Prec (const rl))+#endif++instance (Generic1 f, GRead1 (Rep1 f), Read a) => Read (Generically1 f a) where+#if MIN_VERSION_base(4,10,0)+  readPrec = readPrec1+  readListPrec = readListPrecDefault+#else+  readsPrec = readsPrec1+#endif  instance (Generic1 f, GShow1 (Rep1 f)) => Show1 (Generically1 f) where   liftShowsPrec = gliftShowsPrec
+ src/Generic/Data/Internal/Read.hs view
@@ -0,0 +1,259 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE Trustworthy #-}++-- | Generic implementation of Read+--+-- === Warning+--+-- This is an internal module: it is not subject to any versioning policy,+-- breaking changes can happen at any time.+--+-- If something here seems useful, please report it or create a pull request to+-- export it from an external module.++module Generic.Data.Internal.Read where++import Data.Coerce+import Data.Functor.Classes (Read1(..))+import Data.Functor.Identity+import Data.Proxy+import Generic.Data.Internal.Utils (isSymDataCon, isSymVar)+import GHC.Generics hiding (prec)+import GHC.Read (expectP, list)+import GHC.Show (appPrec, appPrec1)+import Text.ParserCombinators.ReadPrec+import Text.Read (Read(..), parens)+import Text.Read.Lex (Lexeme(..))++-- | Generic 'readPrec'.+--+-- @+-- instance 'Read' MyType where+--   'readPrec' = 'greadPrec'+--   'readListPrec' = 'readListPrecDefault'+-- @+greadPrec :: (Generic a, GRead0 (Rep a)) => ReadPrec a+greadPrec = to <$> gPrecRead Proxy++-- | Generic representation of 'Read' types.+type GRead0 = GRead Proxy++-- | Generic 'liftReadPrec'.+gliftReadPrec+  :: (Generic1 f, GRead1 (Rep1 f))+  => ReadPrec a -> ReadPrec [a]+  -> ReadPrec (f a)+gliftReadPrec readPrec' readList' =+  to1 <$> gPrecRead (Identity (readPrec', readList'))++-- | Generic representation of 'Data.Functor.Classes.Read1' types.+type GRead1 = GRead Identity++class GRead p f where+  gPrecRead :: p (ReadPrec a, ReadPrec [a]) -> ReadPrec (f a)++instance (GRead p f, IsNullaryDataType f) => GRead p (M1 D d f) where+  gPrecRead p = coerceM1 (parensIfNonNullary (gPrecRead p))+    where+      x :: f a+      x = undefined++      parensIfNonNullary :: ReadPrec a -> ReadPrec a+      parensIfNonNullary = if isNullaryDataType x+                              then id+                              else parens++instance (GRead p f, GRead p g) => GRead p (f :+: g) where+  gPrecRead p = fmap L1 (gPrecRead p) +++ fmap R1 (gPrecRead p)++instance (Constructor c, GReadC p c f) => GRead p (M1 C c f) where+  gPrecRead p = gPrecReadC p (conName x) (conFixity x)+    where+      x :: M1 C c f a+      x = undefined++instance GRead p V1 where+  gPrecRead _ = pfail++class IsNullaryDataType f where+  isNullaryDataType :: f a -> Bool++instance IsNullaryDataType (f :+: g) where+  isNullaryDataType _ = False++instance IsNullaryDataType (C1 c f) where+  isNullaryDataType _ = False++instance IsNullaryDataType V1 where+  isNullaryDataType _ = True++class GReadC p c f where+  gPrecReadC :: p (ReadPrec a, ReadPrec [a]) -> String -> Fixity -> ReadPrec (M1 C c f a)++instance GReadFields p f => GReadC p ('MetaCons s y 'False) f where+  gPrecReadC :: forall a. p (ReadPrec a, ReadPrec [a]) -> String -> Fixity+             -> ReadPrec (M1 C ('MetaCons s y 'False) f a)+  gPrecReadC p name fixity+    | Infix _ fy <- fixity, Branch k1 k2 <- fields+    = coerceM1 $ prec fy $ do+        k1' <- toReadPrec k1+        if isSymDataCon name+           then expectP (Symbol name)+           else mapM_ expectP ([Punc "`"] ++ identHLexemes name ++ [Punc "`"])+        k2' <- toReadPrec k2+        pure (k1' :*: k2')+    | otherwise+    = coerceM1 $ prec appPrec $ do+        readPrefixCon name+        toReadPrec fields+    where+      fields :: ReadPrecTree (f a)+      fields = gPrecReadFields p++instance GReadNamed p f => GReadC p ('MetaCons s y 'True) f where+  gPrecReadC p name _fixity = coerceM1 $ prec appPrec1 $ do+    readPrefixCon name+    readSurround '{' fields '}'+    where+      fields = gPrecReadNamed p++class GReadFields p f where+  gPrecReadFields :: p (ReadPrec a, ReadPrec [a]) -> ReadPrecTree (f a)++instance (GReadFields p f, GReadFields p g) => GReadFields p (f :*: g) where+  gPrecReadFields p = Branch (gPrecReadFields p) (gPrecReadFields p)++instance GReadSingle p f => GReadFields p (M1 S c f) where+  gPrecReadFields p = M1Leaf (step (gPrecReadSingle p))++instance GReadFields p U1 where+  gPrecReadFields _ = U1Leaf++class GReadNamed p f where+  gPrecReadNamed :: p (ReadPrec a, ReadPrec [a]) -> ReadPrec (f a)++instance (GReadNamed p f, GReadNamed p g) => GReadNamed p (f :*: g) where+  gPrecReadNamed p = do+    l <- gPrecReadNamed p+    expectP (Punc ",")+    r <- gPrecReadNamed p+    pure (l :*: r)++instance (Selector c, GReadSingle p f) => GReadNamed p (M1 S c f) where+  gPrecReadNamed p = coerceM1 $ do+    mapM_ expectP snameLexemes+    expectP (Punc "=")+    reset (gPrecReadSingle p)+    where+      x :: M1 S c f a+      x = undefined++      sname :: String+      sname = selName x++      snameLexemes :: [Lexeme]+      snameLexemes | isSymVar sname+                   = [Punc "(", Symbol sname, Punc ")"]+                   | otherwise+                   = identHLexemes sname++instance GReadNamed p U1 where+  gPrecReadNamed _ = pure U1++class GReadSingle p f where+  gPrecReadSingle :: p (ReadPrec a, ReadPrec [a]) -> ReadPrec (f a)++instance Read a => GReadSingle p (K1 i a) where+  gPrecReadSingle _ = coerceK1 readPrec+    where+      coerceK1 :: ReadPrec a -> ReadPrec (K1 i a x)+      coerceK1 = coerce++instance Read1 f => GReadSingle Identity (Rec1 f) where+  gPrecReadSingle (Identity p) = coerceRec1 (liftReadPrecCompat p)+    where+      coerceRec1 :: ReadPrec (f a) -> ReadPrec (Rec1 f a)+      coerceRec1 = coerce++instance GReadSingle Identity Par1 where+  gPrecReadSingle (Identity (readPrec', _)) = coercePar1 readPrec'+    where+      coercePar1 :: ReadPrec p -> ReadPrec (Par1 p)+      coercePar1 = coerce++instance (Read1 f, GReadSingle p g) => GReadSingle p (f :.: g) where+  gPrecReadSingle :: forall a. p (ReadPrec a, ReadPrec [a]) -> ReadPrec ((f :.: g) a)+  gPrecReadSingle p = coerceComp1 (liftReadPrecCompat (readPrec_, readList_))+    where+      readPrec_ :: ReadPrec (g a)+      readPrec_ = gPrecReadSingle p++      readList_ :: ReadPrec [g a]+      readList_ = list readPrec_++      coerceComp1 :: ReadPrec (f (g a)) -> ReadPrec ((f :.: g) a)+      coerceComp1 = coerce++-- Helpers++coerceM1 :: ReadPrec (f p) -> ReadPrec (M1 i c f p)+coerceM1 = coerce++-- | A backwards-compatible version of 'liftReadPrec'. This is needed for+-- compatibility with @base-4.9@, where 'Read1' only offers 'liftReadsPrec',+-- not 'liftReadPrec'.+liftReadPrecCompat :: Read1 f => (ReadPrec a, ReadPrec [a]) -> ReadPrec (f a)+liftReadPrecCompat (readPrec', readList') =+#if MIN_VERSION_base(4,10,0)+    liftReadPrec readPrec' readList'+#else+    readS_to_Prec (liftReadsPrec (readPrec_to_S readPrec')+                                 (readPrec_to_S readList' 0))+#endif++data ReadPrecTree a where+  U1Leaf :: ReadPrecTree (U1 a)+  M1Leaf :: ReadPrec (f a) -> ReadPrecTree (M1 i c f a)+  Branch :: ReadPrecTree (f a) -> ReadPrecTree (g a) -> ReadPrecTree ((f :*: g) a)++toReadPrec :: ReadPrecTree a -> ReadPrec a+toReadPrec U1Leaf       = pure U1+toReadPrec (M1Leaf f)   = coerceM1 f+toReadPrec (Branch f g) = (:*:) <$> toReadPrec f <*> toReadPrec g++identHLexemes :: String -> [Lexeme]+identHLexemes s | Just (ss, '#') <- snocView s = [Ident ss, Symbol "#"]+                | otherwise                    = [Ident s]++readPrefixCon :: String -> ReadPrec ()+readPrefixCon name+  | isSymDataCon name+  = readSurround '(' (expectP (Symbol name)) ')'+  | otherwise+  = mapM_ expectP (identHLexemes name)++readSurround :: Char -> ReadPrec a -> Char -> ReadPrec a+readSurround c1 r c2 = do+  expectP (Punc [c1])+  r' <- r+  expectP (Punc [c2])+  pure r'++-- Split off the last element.+snocView :: [a] -> Maybe ([a], a)+snocView [] = Nothing+snocView xs = go [] xs+  where+    -- Invariant: second arg is non-empty+    go acc [a]    = Just (reverse acc, a)+    go acc (a:as) = go (a:acc) as+    go _   []     = error "Util: snocView"
src/Generic/Data/Internal/Show.hs view
@@ -23,7 +23,7 @@ import Data.Functor.Classes (Show1(..)) import Data.Functor.Identity import Data.Proxy-import GHC.Lexeme (startsConSym, startsVarSym)+import Generic.Data.Internal.Utils (isSymDataCon, isSymVar) import GHC.Generics import Text.Show.Combinators @@ -157,11 +157,3 @@       | otherwise -> "`" ++ name ++ "`"   where     isSymName = isSymDataCon name--isSymDataCon :: String -> Bool-isSymDataCon ""    = False-isSymDataCon (c:_) = startsConSym c--isSymVar :: String -> Bool-isSymVar ""    = False-isSymVar (c:_) = startsVarSym c
src/Generic/Data/Internal/Utils.hs view
@@ -2,7 +2,8 @@     BangPatterns,     EmptyCase,     FlexibleContexts,-    PolyKinds #-}+    PolyKinds,+    Trustworthy #-}  -- | Utilities. --@@ -18,6 +19,7 @@  import Data.Coerce import GHC.Generics+import GHC.Lexeme (startsConSym, startsVarSym)  -- | Convert between types with representationally equivalent generic -- representations.@@ -54,3 +56,15 @@ -- | Lift binary combinators generically. liftG2 :: Generic1 f => (Rep1 f a -> Rep1 f b -> Rep1 f c) -> f a -> f b -> f c liftG2 = \(<?>) a b -> to1 (from1 a <?> from1 b)++-- | Returns 'True' if the argument is a symbolic data constructor name+-- (e.g., @(:+:)@). Returns 'False' otherwise.+isSymDataCon :: String -> Bool+isSymDataCon ""    = False+isSymDataCon (c:_) = startsConSym c++-- | Returns 'True' if the argument is a symbolic value name (e.g., @(+++)@).+-- Returns 'False' otherwise.+isSymVar :: String -> Bool+isSymVar ""    = False+isSymVar (c:_) = startsVarSym c
test/record.hs view
@@ -12,6 +12,7 @@ import Data.Semigroup import Data.Monoid (Alt(..)) import GHC.Generics (Generic)+import Text.Read  import Generic.Data import Generic.Data.Orphans ()@@ -20,6 +21,10 @@   { _field1 :: f Int   , _field2 :: f Bool   } deriving Generic++instance Read1 f => Read (MyRecord f) where+  readPrec = coerce (greadPrec @(MyRecord (Id1 f)))+  readListPrec = readListPrecDefault  instance Show1 f => Show (MyRecord f) where   showsPrec = coerce (gshowsPrec @(MyRecord (Id1 f)))
test/unit.hs view
@@ -11,6 +11,7 @@ import Data.Functor.Classes import Test.Tasty import Test.Tasty.HUnit+import Text.Read  import GHC.Generics import Generic.Data@@ -78,6 +79,29 @@ newtype MyCompose f g a = MyCompose (f (g a))   deriving Generic1 +instance (Functor f, Eq1 f, Eq1 g) => Eq1 (MyCompose f g) where+  liftEq = gliftEq++instance (Functor f, Eq1 f, Eq1 g, Eq a) => Eq (MyCompose f g a) where+  (==) = eq1++instance (Functor f, Read1 f, Read1 g) => Read1 (MyCompose f g) where+#if MIN_VERSION_base(4,10,0)+  liftReadPrec = gliftReadPrec+  liftReadListPrec = liftReadListPrecDefault+#else+  liftReadsPrec rp rl = readPrec_to_S $+    gliftReadPrec (readS_to_Prec rp) (readS_to_Prec (const rl))+#endif++instance (Functor f, Read1 f, Read1 g, Read a) => Read (MyCompose f g a) where+#if MIN_VERSION_base(4,10,0)+  readPrec = readPrec1+  readListPrec = readListPrecDefault+#else+  readsPrec = readsPrec1+#endif+ instance (Functor f, Show1 f, Show1 g) => Show1 (MyCompose f g) where   liftShowsPrec = gliftShowsPrec @@ -92,9 +116,23 @@           | () `MkT30b` ()   deriving Generic +instance Eq T30a where+  (==) = geq++instance Read T30a where+  readPrec = greadPrec+  readListPrec = readListPrecDefault+ instance Show T30a where   showsPrec = gshowsPrec +instance Eq T30b where+  (==) = geq++instance Read T30b where+  readPrec = greadPrec+  readListPrec = readListPrecDefault+ instance Show T30b where   showsPrec = gshowsPrec @@ -186,6 +224,14 @@         ]       , testCase "single nullary constructor" $ 0 @=? gindex (Unit, Unit) Unit       ]+  , testGroup "Read"+      [ testCase "read" $ p' 1 2 @=? read "(P 1 2)"+      , testGroup "T30"+        [ testCase "MkT30a" $ MkT30a {(##) = ()} @=? read "(MkT30a {(##) = ()})"+        , testCase "(:!:)" $ (:!:) () () @=? read "(:!:) () ()"+        , testCase "MkT30b" $ (() `MkT30b` ()) @=? read "() `MkT30b` ()"+        ]+      ]   , testGroup "Show"       [ testCase "show" $ "P 1 2" @=? show (p' 1 2)       , testCase "showsPrec" $ "(P 1 2)" @=? showsPrec 11 (p' 1 2) ""@@ -196,6 +242,9 @@         ]       ] +  , testGroup "Read1"+      [ testCase "read1" $ MyCompose (Just [()]) @?= read "(MyCompose (Just [()]))"+      ]   , testGroup "Show1"       [ testCase "show1" $ "MyCompose (Just [()])" @?= show (MyCompose (Just [()]))       ]