2014-10-16 6 views
72

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

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

+2

Я уверен, что вы не можете сделать это только с помощью TH, но вы можете использовать 'haskell-src-meta' для анализа модуля Haskell как TH AST. – user2407038

+1

Для этого потребуется использовать функции ввода-вывода '' 'монады для загрузки модуля, а затем отправить это' haskell-src-meta'? Хлоп. Кроме того, это не может устранить неоднозначность имени, которое будет использоваться в конкретной области, в которой находится сращивание. –

+1

Да, вам нужно использовать IO для фактического чтения файла. Я не уверен, что понимаю ваше второе утверждение - зачем вам нужно устранять неоднозначность, если вы получаете * все * имена? Вы можете открыть билет для запроса функции, я подозреваю, что основной механизм, который поддерживает TH, имеет все имена в области видимости, доступные в любом случае. – user2407038

ответ

1

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

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

Пожалуйста, ссылку https://ghc.haskell.org/trac/ghc/ticket/9699#ticket, чтобы увидеть текущее Грубый SPEC

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

(2) Добавьте этот модуль: Модуль 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.