Using TemplateHaskell to list all names in a namespace
I want a TemplateHaskell function variablesInScope :: Q [Name]
that returns a list of the Name
's of all the variables in scope. TemplateHaskell obviously has this information available in order to implement functions like reify :: Name -> Q Info
and lookupValueName :: String -> Q (Maybe Name)
.
Does the function I want exist somewhere and I just overlooked it? Or can it be easily built somehow?
Solution 1:
Unfortunately, you cannot do this with TH
alone. Try the haskell-src-meta
to parse the Haskell module as a TH AST
.
It will require the IO features of the Q
monad to load the module though.
Please reference https://ghc.haskell.org/trac/ghc/ticket/9699#ticket to see the current rough spec
(1) Extend ModuleInfo (obtained from reifyModule) to ModuleInfo [Module] [Name], where [Module] is still the import list and [Name] contains the module's list of exported names.
(2) Add thisModule :: Q Module producing the current Module.
(3) Add topLevelNames :: Q [Name] producing a list of top-level names (both exported and non-exported) bound in the current module that would be visible to reify.
(4) Add nestedNames :: Q [Name] (in need of a better name) producing a list of the non-top-level (nested) names visible to reify in this context.
(5) Add parentNames :: Q [Name] (also in need of a better name) producing a list of the names immediately associated with the current splicing context, if available. For example, foo, bar :: $(typeSplice) would see [foo, bar], foo = $(exprSplice) would see [foo], and $(topLevelDecSplice) would see [].
(6) Optional Add isTopLevel :: Name -> Q Bool to detect whether a name is bound at the top level (of the current module?). Something like this could alternately be accomplished by searching through topLevelNames.