diff --git a/generics-sop/generics-sop.cabal b/generics-sop/generics-sop.cabal index c84ac93..4408371 100644 --- a/generics-sop/generics-sop.cabal +++ b/generics-sop/generics-sop.cabal @@ -70,6 +70,9 @@ library template-haskell >= 2.8 && < 2.21, th-abstraction >= 0.4 && < 0.6, ghc-prim >= 0.3 && < 0.11 + if impl(ghc < 9.4.1) + build-depends: generically + hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall diff --git a/generics-sop/src/Generics/SOP.hs b/generics-sop/src/Generics/SOP.hs index 9b13241..350f5c0 100644 --- a/generics-sop/src/Generics/SOP.hs +++ b/generics-sop/src/Generics/SOP.hs @@ -195,6 +195,39 @@ -- > instance NFData A where rnf = grnf -- > instance NFData a => NFData (B a) where rnf = grnf -- +-- == Deriving Generic +-- +-- The 'Generic' class can also be derived in two ways +-- (this uses @-XDerivingStrategies@ for more clarity) +-- +-- === Using @-XDeriveAnyClass@ +-- +-- > {-# LANGUAGE DeriveGeneric, DerivingStrategies, DeriveAnyClass #-} +-- > +-- > import qualified GHC.Generics as GHC +-- > import Generics.SOP +-- > data A = B Bool | C Int +-- > deriving stock GHC.Generic +-- > deriving anyclass Generic +-- +-- === Using @-XDerivingVia@ (GHC versions greater or equal 8.6.1) +-- +-- > {-# LANGUAGE DeriveGeneric, DerivingStrategies, DerivingVia #-} +-- > +-- > import qualified GHC.Generics as GHC +-- > import Generics.SOP +-- > import GHC.Generics (Generically (Generically)) +-- > data A = B Bool | C Int +-- > deriving stock GHC.Generic +-- > deriving Generic via Generically A +-- +-- In the @-XDerivingVia@ case be careful to +-- +-- 1. import the constructor of 'Generically' +-- 2. import the correct module i.e. on base versions older than 4.17 which was +-- first shipped with GHC 9.4.1 @import GHC.Generics.Generically (Generically (Generically))@ +-- from package [@generically@](https://hackage.haskell.org/package/generically) +-- -- = More examples -- -- The best way to learn about how to define generic functions in the SOP style diff --git a/generics-sop/src/Generics/SOP/Universe.hs b/generics-sop/src/Generics/SOP/Universe.hs index 4b67a48..42a1983 100644 --- a/generics-sop/src/Generics/SOP/Universe.hs +++ b/generics-sop/src/Generics/SOP/Universe.hs @@ -1,5 +1,6 @@ {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableSuperClasses #-} +{-# LANGUAGE CPP #-} -- | Codes and interpretations module Generics.SOP.Universe where @@ -8,6 +9,12 @@ import Data.Coerce (Coercible, coerce) import Data.Proxy import qualified GHC.Generics as GHC +#if MIN_VERSION_base(4,17,0) +import GHC.Generics (Generically(Generically)) +#else +import GHC.Generics.Generically(Generically(Generically)) +#endif + import Generics.SOP.BasicFunctors import Generics.SOP.Constraint import Generics.SOP.NP @@ -15,6 +22,7 @@ import Generics.SOP.NS import Generics.SOP.GGP import Generics.SOP.Metadata import qualified Generics.SOP.Type.Metadata as T +import Language.Haskell.TH (Extension(DeriveLift)) -- | The (generic) representation of a datatype. -- @@ -270,3 +278,35 @@ newtypeFrom = coerce newtypeTo :: IsNewtype a x => x -> a newtypeTo = coerce {-# INLINE newtypeTo #-} + +#if MIN_VERSION_GLASGOW_HASKELL(8,6,1,0) +-- | Derive 'Generic' via 'Generically' +-- +-- /Example:/ +-- +-- >>> :set -XDerivingStrategies -XDerivingVia -XDeriveGeneric -XUndecidableInstances +-- >>> data A = B Int | C Bool deriving stock GHC.Generic deriving Generic via Generically A +-- >>> :kind! Code A +-- Code A :: [[*]] +-- = '[ '[Int], '[Bool]] +-- >>> from (B 4) +-- SOP (Z (I 4 :* Nil)) +-- >>> from (C False) +-- SOP (S (Z (I False :* Nil))) +-- +-- @since 0.5.2.0 +#else +-- | Derive 'Generic' via 'Generically' +-- +-- @since 0.5.2.0 +#endif +instance + (GHC.Generic a + , GFrom a + , GTo a + , Rep a ~ SOP I (GCode a) + , All SListI (Code a) + ) => Generic (Generically a) where + type Code (Generically a) = GCode a + from (Generically a) = gfrom a + to rep = Generically (gto rep)