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.