summaryrefslogtreecommitdiff
path: root/libraries
diff options
context:
space:
mode:
authorRyan Scott <ryan.gl.scott@gmail.com>2016-09-30 20:15:25 -0400
committerBen Gamari <ben@smart-cactus.org>2016-09-30 23:23:44 -0400
commit9e862765ffe161da8a4fd9cd67b0a600874feaa9 (patch)
tree235c1ba702b0101e1fa6a8fe7f8146e2c7ec9c69 /libraries
parentb3d55e20d20344bfc09f4ca4a554a819c4ecbfa8 (diff)
downloadhaskell-9e862765ffe161da8a4fd9cd67b0a600874feaa9.tar.gz
Implement deriving strategies
Allows users to explicitly request which approach to `deriving` to use via keywords, e.g., ``` newtype Foo = Foo Bar deriving Eq deriving stock Ord deriving newtype Show ``` Fixes #10598. Updates haddock submodule. Test Plan: ./validate Reviewers: hvr, kosmikus, goldfire, alanz, bgamari, simonpj, austin, erikd, simonmar Reviewed By: alanz, bgamari, simonpj Subscribers: thomie, mpickering, oerjan Differential Revision: https://phabricator.haskell.org/D2280 GHC Trac Issues: #10598
Diffstat (limited to 'libraries')
-rw-r--r--libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs1
-rw-r--r--libraries/ghci/GHCi/TH/Binary.hs2
-rw-r--r--libraries/template-haskell/Language/Haskell/TH.hs13
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Lib.hs32
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Ppr.hs29
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Syntax.hs40
-rw-r--r--libraries/template-haskell/changelog.md3
7 files changed, 87 insertions, 33 deletions
diff --git a/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs b/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs
index 85664c2144..ff26ec6ce7 100644
--- a/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs
+++ b/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs
@@ -80,6 +80,7 @@ data Extension
| DefaultSignatures -- Allow extra signatures for defmeths
| DeriveAnyClass -- Allow deriving any class
| DeriveLift -- Allow deriving Lift
+ | DerivingStrategies
| TypeSynonymInstances
| FlexibleContexts
diff --git a/libraries/ghci/GHCi/TH/Binary.hs b/libraries/ghci/GHCi/TH/Binary.hs
index 0bdc756870..e93095662e 100644
--- a/libraries/ghci/GHCi/TH/Binary.hs
+++ b/libraries/ghci/GHCi/TH/Binary.hs
@@ -30,6 +30,8 @@ instance Binary TH.Pat
instance Binary TH.Exp
instance Binary TH.Dec
instance Binary TH.Overlap
+instance Binary TH.DerivClause
+instance Binary TH.DerivStrategy
instance Binary TH.Guard
instance Binary TH.Body
instance Binary TH.Match
diff --git a/libraries/template-haskell/Language/Haskell/TH.hs b/libraries/template-haskell/Language/Haskell/TH.hs
index 7cf342a460..bde698eaa3 100644
--- a/libraries/template-haskell/Language/Haskell/TH.hs
+++ b/libraries/template-haskell/Language/Haskell/TH.hs
@@ -85,11 +85,11 @@ module Language.Haskell.TH(
-- * Library functions
-- ** Abbreviations
- InfoQ, ExpQ, DecQ, DecsQ, ConQ, TypeQ, TyLitQ, CxtQ, PredQ, MatchQ,
- ClauseQ, BodyQ, GuardQ, StmtQ, RangeQ, SourceStrictnessQ,
- SourceUnpackednessQ, BangTypeQ, VarBangTypeQ, StrictTypeQ,
- VarStrictTypeQ, PatQ, FieldPatQ, RuleBndrQ, TySynEqnQ, PatSynDirQ,
- PatSynArgsQ,
+ InfoQ, ExpQ, DecQ, DecsQ, ConQ, TypeQ, TyLitQ, CxtQ, PredQ,
+ DerivClauseQ, MatchQ, ClauseQ, BodyQ, GuardQ, StmtQ, RangeQ,
+ SourceStrictnessQ, SourceUnpackednessQ, BangTypeQ, VarBangTypeQ,
+ StrictTypeQ, VarStrictTypeQ, PatQ, FieldPatQ, RuleBndrQ, TySynEqnQ,
+ PatSynDirQ, PatSynArgsQ,
-- ** Constructors lifted to 'Q'
-- *** Literals
@@ -144,9 +144,10 @@ module Language.Haskell.TH(
-- *** Top Level Declarations
-- **** Data
valD, funD, tySynD, dataD, newtypeD,
+ derivClause, DerivClause(..), DerivStrategy(..),
-- **** Class
classD, instanceD, instanceWithOverlapD, Overlap(..),
- sigD, standaloneDerivD, defaultSigD,
+ sigD, standaloneDerivD, standaloneDerivWithStrategyD, defaultSigD,
-- **** Role annotations
roleAnnotD,
diff --git a/libraries/template-haskell/Language/Haskell/TH/Lib.hs b/libraries/template-haskell/Language/Haskell/TH/Lib.hs
index 2631c0e32d..c42543863d 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Lib.hs
+++ b/libraries/template-haskell/Language/Haskell/TH/Lib.hs
@@ -30,6 +30,7 @@ type TypeQ = Q Type
type TyLitQ = Q TyLit
type CxtQ = Q Cxt
type PredQ = Q Pred
+type DerivClauseQ = Q DerivClause
type MatchQ = Q Match
type ClauseQ = Q Clause
type BodyQ = Q Body
@@ -360,20 +361,22 @@ funD nm cs =
tySynD :: Name -> [TyVarBndr] -> TypeQ -> DecQ
tySynD tc tvs rhs = do { rhs1 <- rhs; return (TySynD tc tvs rhs1) }
-dataD :: CxtQ -> Name -> [TyVarBndr] -> Maybe Kind -> [ConQ] -> CxtQ -> DecQ
+dataD :: CxtQ -> Name -> [TyVarBndr] -> Maybe Kind -> [ConQ] -> [DerivClauseQ]
+ -> DecQ
dataD ctxt tc tvs ksig cons derivs =
do
ctxt1 <- ctxt
cons1 <- sequence cons
- derivs1 <- derivs
+ derivs1 <- sequence derivs
return (DataD ctxt1 tc tvs ksig cons1 derivs1)
-newtypeD :: CxtQ -> Name -> [TyVarBndr] -> Maybe Kind -> ConQ -> CxtQ -> DecQ
+newtypeD :: CxtQ -> Name -> [TyVarBndr] -> Maybe Kind -> ConQ -> [DerivClauseQ]
+ -> DecQ
newtypeD ctxt tc tvs ksig con derivs =
do
ctxt1 <- ctxt
con1 <- con
- derivs1 <- derivs
+ derivs1 <- sequence derivs
return (NewtypeD ctxt1 tc tvs ksig con1 derivs1)
classD :: CxtQ -> Name -> [TyVarBndr] -> [FunDep] -> [DecQ] -> DecQ
@@ -452,22 +455,24 @@ pragAnnD target expr
pragLineD :: Int -> String -> DecQ
pragLineD line file = return $ PragmaD $ LineP line file
-dataInstD :: CxtQ -> Name -> [TypeQ] -> Maybe Kind -> [ConQ] -> CxtQ -> DecQ
+dataInstD :: CxtQ -> Name -> [TypeQ] -> Maybe Kind -> [ConQ] -> [DerivClauseQ]
+ -> DecQ
dataInstD ctxt tc tys ksig cons derivs =
do
ctxt1 <- ctxt
tys1 <- sequence tys
cons1 <- sequence cons
- derivs1 <- derivs
+ derivs1 <- sequence derivs
return (DataInstD ctxt1 tc tys1 ksig cons1 derivs1)
-newtypeInstD :: CxtQ -> Name -> [TypeQ] -> Maybe Kind -> ConQ -> CxtQ -> DecQ
+newtypeInstD :: CxtQ -> Name -> [TypeQ] -> Maybe Kind -> ConQ -> [DerivClauseQ]
+ -> DecQ
newtypeInstD ctxt tc tys ksig con derivs =
do
ctxt1 <- ctxt
tys1 <- sequence tys
con1 <- con
- derivs1 <- derivs
+ derivs1 <- sequence derivs
return (NewtypeInstD ctxt1 tc tys1 ksig con1 derivs1)
tySynInstD :: Name -> TySynEqnQ -> DecQ
@@ -534,11 +539,14 @@ roleAnnotD :: Name -> [Role] -> DecQ
roleAnnotD name roles = return $ RoleAnnotD name roles
standaloneDerivD :: CxtQ -> TypeQ -> DecQ
-standaloneDerivD ctxtq tyq =
+standaloneDerivD = standaloneDerivWithStrategyD Nothing
+
+standaloneDerivWithStrategyD :: Maybe DerivStrategy -> CxtQ -> TypeQ -> DecQ
+standaloneDerivWithStrategyD ds ctxtq tyq =
do
ctxt <- ctxtq
ty <- tyq
- return $ StandaloneDerivD ctxt ty
+ return $ StandaloneDerivD ds ctxt ty
defaultSigD :: Name -> TypeQ -> DecQ
defaultSigD n tyq =
@@ -570,6 +578,10 @@ tySynEqn lhs rhs =
cxt :: [PredQ] -> CxtQ
cxt = sequence
+derivClause :: Maybe DerivStrategy -> [PredQ] -> DerivClauseQ
+derivClause ds p = do p' <- cxt p
+ return $ DerivClause ds p'
+
normalC :: Name -> [BangTypeQ] -> ConQ
normalC con strtys = liftM (NormalC con) $ sequence strtys
diff --git a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs
index 7376135ed0..8941a8ba81 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs
+++ b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs
@@ -358,8 +358,12 @@ ppr_dec _ (ClosedTypeFamilyD tfhead@(TypeFamilyHead tc _ _ _) eqns)
= ppr tc <+> sep (map pprParendType lhs) <+> text "=" <+> ppr rhs
ppr_dec _ (RoleAnnotD name roles)
= hsep [ text "type role", ppr name ] <+> hsep (map ppr roles)
-ppr_dec _ (StandaloneDerivD cxt ty)
- = hsep [ text "deriving instance", pprCxt cxt, ppr ty ]
+ppr_dec _ (StandaloneDerivD ds cxt ty)
+ = hsep [ text "deriving"
+ , maybe empty ppr_deriv_strategy ds
+ , text "instance"
+ , pprCxt cxt
+ , ppr ty ]
ppr_dec _ (DefaultSigD n ty)
= hsep [ text "default", pprPrefixOcc n, dcolon, ppr ty ]
ppr_dec _ (PatSynD name args dir pat)
@@ -373,6 +377,12 @@ ppr_dec _ (PatSynD name args dir pat)
ppr_dec _ (PatSynSigD name ty)
= pprPatSynSig name ty
+ppr_deriv_strategy :: DerivStrategy -> Doc
+ppr_deriv_strategy ds = text $
+ case ds of
+ Stock -> "stock"
+ Anyclass -> "anyclass"
+ Newtype -> "newtype"
ppr_overlap :: Overlap -> Doc
ppr_overlap o = text $
@@ -382,7 +392,8 @@ ppr_overlap o = text $
Overlapping -> "{-# OVERLAPPING #-}"
Incoherent -> "{-# INCOHERENT #-}"
-ppr_data :: Doc -> Cxt -> Name -> Doc -> Maybe Kind -> [Con] -> Cxt -> Doc
+ppr_data :: Doc -> Cxt -> Name -> Doc -> Maybe Kind -> [Con] -> [DerivClause]
+ -> Doc
ppr_data maybeInst ctxt t argsDoc ksig cs decs
= sep [text "data" <+> maybeInst
<+> pprCxt ctxt
@@ -391,7 +402,7 @@ ppr_data maybeInst ctxt t argsDoc ksig cs decs
if null decs
then empty
else nest nestDepth
- $ text "deriving" <+> ppr_cxt_preds decs]
+ $ vcat $ map ppr_deriv_clause decs]
where
pref :: [Doc] -> [Doc]
pref xs | isGadtDecl = xs
@@ -413,7 +424,8 @@ ppr_data maybeInst ctxt t argsDoc ksig cs decs
Nothing -> empty
Just k -> dcolon <+> ppr k
-ppr_newtype :: Doc -> Cxt -> Name -> Doc -> Maybe Kind -> Con -> Cxt -> Doc
+ppr_newtype :: Doc -> Cxt -> Name -> Doc -> Maybe Kind -> Con -> [DerivClause]
+ -> Doc
ppr_newtype maybeInst ctxt t argsDoc ksig c decs
= sep [text "newtype" <+> maybeInst
<+> pprCxt ctxt
@@ -422,12 +434,17 @@ ppr_newtype maybeInst ctxt t argsDoc ksig c decs
if null decs
then empty
else nest nestDepth
- $ text "deriving" <+> ppr_cxt_preds decs]
+ $ vcat $ map ppr_deriv_clause decs]
where
ksigDoc = case ksig of
Nothing -> empty
Just k -> dcolon <+> ppr k
+ppr_deriv_clause :: DerivClause -> Doc
+ppr_deriv_clause (DerivClause ds ctxt)
+ = text "deriving" <+> maybe empty ppr_deriv_strategy ds
+ <+> ppr_cxt_preds ctxt
+
ppr_tySyn :: Doc -> Name -> Doc -> Type -> Doc
ppr_tySyn maybeInst t argsDoc rhs
= text "type" <+> maybeInst <+> ppr t <+> argsDoc <+> text "=" <+> ppr rhs
diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
index 00ac0b308b..afe961b50e 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
+++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
@@ -1549,13 +1549,15 @@ data Dec
| ValD Pat Body [Dec] -- ^ @{ p = b where decs }@
| DataD Cxt Name [TyVarBndr]
(Maybe Kind) -- Kind signature (allowed only for GADTs)
- [Con] Cxt
+ [Con] [DerivClause]
-- ^ @{ data Cxt x => T x = A x | B (T x)
- -- deriving (Z,W)}@
+ -- deriving (Z,W)
+ -- deriving stock Eq }@
| NewtypeD Cxt Name [TyVarBndr]
(Maybe Kind) -- Kind signature
- Con Cxt -- ^ @{ newtype Cxt x => T x = A (B x)
- -- deriving (Z,W Q)}@
+ Con [DerivClause] -- ^ @{ newtype Cxt x => T x = A (B x)
+ -- deriving (Z,W Q)
+ -- deriving stock Eq }@
| TySynD Name [TyVarBndr] Type -- ^ @{ type T x = (x,x) }@
| ClassD Cxt Name [TyVarBndr]
[FunDep] [Dec] -- ^ @{ class Eq a => Ord a where ds }@
@@ -1578,14 +1580,18 @@ data Dec
| DataInstD Cxt Name [Type]
(Maybe Kind) -- Kind signature
- [Con] Cxt -- ^ @{ data instance Cxt x => T [x]
- -- = A x | B (T x) deriving (Z,W)}@
+ [Con] [DerivClause] -- ^ @{ data instance Cxt x => T [x]
+ -- = A x | B (T x)
+ -- deriving (Z,W)
+ -- deriving stock Eq }@
| NewtypeInstD Cxt Name [Type]
- (Maybe Kind) -- Kind signature
- Con Cxt -- ^ @{ newtype instance Cxt x => T [x]
- -- = A (B x) deriving (Z,W)}@
- | TySynInstD Name TySynEqn -- ^ @{ type instance ... }@
+ (Maybe Kind) -- Kind signature
+ Con [DerivClause] -- ^ @{ newtype instance Cxt x => T [x]
+ -- = A (B x)
+ -- deriving (Z,W)
+ -- deriving stock Eq }@
+ | TySynInstD Name TySynEqn -- ^ @{ type instance ... }@
-- | open type families (may also appear in [Dec] of 'ClassD' and 'InstanceD')
| OpenTypeFamilyD TypeFamilyHead
@@ -1595,7 +1601,8 @@ data Dec
-- ^ @{ type family F a b = (r :: *) | r -> a where ... }@
| RoleAnnotD Name [Role] -- ^ @{ type role T nominal representational }@
- | StandaloneDerivD Cxt Type -- ^ @{ deriving instance Ord a => Ord (Foo a) }@
+ | StandaloneDerivD (Maybe DerivStrategy) Cxt Type
+ -- ^ @{ deriving stock instance Ord a => Ord (Foo a) }@
| DefaultSigD Name Type -- ^ @{ default size :: Data a => a -> Int }@
-- | Pattern Synonyms
@@ -1620,6 +1627,17 @@ data Overlap = Overlappable -- ^ May be overlapped by more specific instances
-- available.
deriving( Show, Eq, Ord, Data, Generic )
+-- | A single @deriving@ clause at the end of a datatype.
+data DerivClause = DerivClause (Maybe DerivStrategy) Cxt
+ -- ^ @{ deriving stock (Eq, Ord) }@
+ deriving( Show, Eq, Ord, Data, Generic )
+
+-- | What the user explicitly requests when deriving an instance.
+data DerivStrategy = Stock -- ^ A \"standard\" derived instance
+ | Anyclass -- ^ @-XDeriveAnyClass@
+ | Newtype -- ^ @-XGeneralizedNewtypeDeriving@
+ deriving( Show, Eq, Ord, Data, Generic )
+
-- | A Pattern synonym's type. Note that a pattern synonym's *fully*
-- specified type has a peculiar shape coming with two forall
-- quantifiers and two constraint contexts. For example, consider the
diff --git a/libraries/template-haskell/changelog.md b/libraries/template-haskell/changelog.md
index e23fbf7db1..19038c755e 100644
--- a/libraries/template-haskell/changelog.md
+++ b/libraries/template-haskell/changelog.md
@@ -12,6 +12,9 @@
* Add support for visible type applications. (#12530)
+ * Add support for attaching deriving strategies to `deriving` statements
+ (#10598)
+
## 2.11.0.0 *May 2016*
* Bundled with GHC 8.0.1