summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorparsonsmatt <parsonsmatt@gmail.com>2021-04-29 11:17:14 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-05-29 05:05:18 -0400
commit6412bf6e1e8c70ae96203190f460be243d961c59 (patch)
tree6f66413909ec04cc95885731861f171f24622a22
parent28e0dca2e93dabee88f28ce38282dbcb8c62ab99 (diff)
downloadhaskell-6412bf6e1e8c70ae96203190f460be243d961c59.tar.gz
Add `newDeclarationGroup` and provide documentation in reifyInstances and isInstance
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Syntax.hs62
1 files changed, 62 insertions, 0 deletions
diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
index d3c5a5eb45..4e0ceb4eef 100644
--- a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
+++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
@@ -568,6 +568,60 @@ This works even if there's no explicit signature and the type or kind is inferre
reifyType :: Name -> Q Type
reifyType nm = Q (qReifyType nm)
+{- | Template Haskell is capable of reifying information about types and
+terms defined in previous declaration groups. Top-level splices break up
+declaration groups.
+
+For an example, consider this code block. We define a datatype @X@ and
+then try to call 'reify' on the datatype.
+
+@
+module Check where
+
+data X = X
+ deriving Eq
+
+$(do
+ info <- reify ''X
+ runIO $ print info
+ )
+@
+
+This code fails to compile, noting that @X@ is not in scope at the site of 'reify'. We can fix this by creating a new declaration group using an empty top-level splice:
+
+@
+data X = X
+ deriving Eq
+
+$(pure [])
+
+$(do
+ info <- reify ''X
+ runIO $ print info
+ )
+@
+
+We provide 'newDeclarationGroup' as a means of documenting this behavior
+and providing a name for the pattern.
+
+Since top level splices infer the presence of the @$( ... )@ brackets, we can also write:
+
+@
+data X = X
+ deriving Eq
+
+newDeclarationGroup
+
+$(do
+ info <- reify ''X
+ runIO $ print info
+ )
+@
+
+-}
+newDeclarationGroup :: Q [Dec]
+newDeclarationGroup = pure []
+
{- | @reifyInstances nm tys@ returns a list of visible instances of @nm tys@. That is,
if @nm@ is the name of a type class, then all instances of this class at the types @tys@
are returned. Alternatively, if @nm@ is the name of a data family or type family,
@@ -585,6 +639,10 @@ instance heads which unify with @nm tys@, they need not actually be satisfiable.
There is one edge case: @reifyInstances ''Typeable tys@ currently always
produces an empty list (no matter what @tys@ are given).
+
+An instance is visible if it is imported or defined in a prior top-level
+declaration group. See the documentation for 'newDeclarationGroup' for more details.
+
-}
reifyInstances :: Name -> [Type] -> Q [InstanceDec]
reifyInstances cls tys = Q (qReifyInstances cls tys)
@@ -625,6 +683,10 @@ reifyConStrictness :: Name -> Q [DecidedStrictness]
reifyConStrictness n = Q (qReifyConStrictness n)
-- | Is the list of instances returned by 'reifyInstances' nonempty?
+--
+-- If you're confused by an instance not being visible despite being
+-- defined in the same module and above the splice in question, see the
+-- docs for 'newDeclarationGroup' for a possible explanation.
isInstance :: Name -> [Type] -> Q Bool
isInstance nm tys = do { decs <- reifyInstances nm tys
; return (not (null decs)) }