Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Derive generic for solo in base >= 4.15 #170

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions generics-sop/generics-sop.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 33 additions & 0 deletions generics-sop/src/Generics/SOP.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions generics-sop/src/Generics/SOP/Instances.hs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ import Text.Read.Lex
import Generics.SOP.BasicFunctors
import Generics.SOP.Classes
import Generics.SOP.TH
#if MIN_VERSION_base(4,15,0)
import GHC.Tuple (Solo)
#endif

-- Types from Generics.SOP:

Expand All @@ -90,6 +93,9 @@ deriveGeneric ''Ordering
deriveGeneric ''Maybe
deriveGeneric ''Either
deriveGeneric ''()
#if MIN_VERSION_base(4,15,0)
deriveGeneric ''Solo
#endif
deriveGeneric ''(,) -- 2
deriveGeneric ''(,,)
deriveGeneric ''(,,,)
Expand Down
40 changes: 40 additions & 0 deletions generics-sop/src/Generics/SOP/Universe.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}
{-# LANGUAGE CPP #-}
-- | Codes and interpretations
module Generics.SOP.Universe where

Expand All @@ -8,13 +9,20 @@ 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
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.
--
Expand Down Expand Up @@ -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)