Использование TemplateHaskell для перечисления всех имен в пространстве имен

Мне нужна функция TemplateHaskell variablesInScope :: Q [Name], которая возвращает список Name всех переменных в области видимости. TemplateHaskell, очевидно, имеет эту информацию для реализации таких функций, как reify :: Name -> Q Info и lookupValueName :: String -> Q (Maybe Name).

Я хочу, чтобы существовала какая-то функция, и я просто забыл об этом? Или его можно легко построить каким-то образом?

Ответ 1

К сожалению, вы не можете сделать это только с помощью TH. Попробуйте haskell-src-meta проанализировать модуль Haskell как TH AST.

Для загрузки модуля потребуются функции ввода-вывода монады Q.

Обращайтесь к https://ghc.haskell.org/trac/ghc/ticket/9699#ticket, чтобы увидеть текущую грубую спецификацию

(1) Расширьте ModuleInfo (полученный из reifyModule) в ModuleInfo [Module] [Name], где [Module] все еще является списком импорта, а [Name] содержит список экспортированных имен модулей.

(2) Добавьте модуль Module: Q, создающий текущий модуль.

(3) Добавить topLevelNames:: Q [Name], создавая список имен верхнего уровня (как экспортированных, так и не экспортируемых), связанных в текущем модуле, которые будут видимы для подтверждения.

(4) Добавьте nestedNames:: Q [Name] (требуется более точное имя), создавая список имен верхнего уровня (вложенных), видимых для подтверждения в этом контексте.

(5) Добавить parentNames:: Q [Name] (также нуждающееся в более лучшем имени), создавая список имен, непосредственно связанных с текущим контекстом сращивания, если он доступен. Например, foo, bar:: $(typeSplice) увидит, что [foo, bar], foo = $(exprSplice) увидит [foo], а $(topLevelDecSplice) увидит [].

(6) Необязательный Добавить isTopLevel:: Name → Q Bool, чтобы определить, связано ли имя на верхнем уровне (текущего модуля?). Что-то вроде этого можно было бы поочередно выполнить путем поиска через topLevelNames.