使用TemplateHaskell列出命名空间中的所有名称

72
我希望有一个 TemplateHaskell 函数 variablesInScope :: Q [Name],返回当前作用域中所有变量的Name列表。显然,TemplateHaskell 已经可以获取这个信息并实现一些函数,例如 reify :: Name -> Q InfolookupValueName :: String -> Q (Maybe Name)
是否已经存在我需要的函数但我忽略了它? 或者说有没有办法轻松地构建它?

2
我相当确定你不能仅使用TH来完成这个任务,但是你可以使用haskell-src-meta将Haskell模块解析为TH AST。 - user2407038
1
需要使用Q单子的IO特性来加载模块,然后将其发送到haskell-src-meta吗?哎呀。此外,这无法消除在剪辑所在的特定范围内要使用哪个名称的歧义。 - Mike Izbicki
1
是的,您需要使用IO来实际读取文件。我不确定我理解您的第二个声明 - 如果您获取所有名称,为什么需要消除歧义?您可以为功能请求打开一个工单,我怀疑支持TH的基础机制已经提供了所有范围内的名称。 - user2407038
1
我创建了票据 (#9699). 我所说的第二个点是一个函数可能声明一个名为 print 的变量,那么 System.IO 中的 print 将不再在范围内。因此,variablesInScope 的结果相当依赖于代码片段出现的位置。 - Mike Izbicki
1个回答

2

很遗憾,你不能仅使用TH实现此功能。尝试使用haskell-src-meta将Haskell模块解析为TH AST

但是,这需要Q单子的IO特性来加载模块。

请参考https://ghc.haskell.org/trac/ghc/ticket/9699#ticket查看当前的粗略规范

(1) 扩展​ModuleInfo(从​reifyModule获得)到ModuleInfo [Module] [Name],其中[Module]仍然是导入列表,而[Name]包含模块的导出名称列表。

(2) 添加thisModule :: Q Module,生成当前​Module。

(3) 添加topLevelNames :: Q [Name],生成在当前模块中绑定的顶层名称(包括导出和非导出的名称),这些名称对于reify可见。

(4) 添加nestedNames :: Q [Name](需要更好的名称),生成在此上下文中对reify可见的非顶级(嵌套)名称列表。

(5) 添加parentNames :: Q [Name](同样需要更好的名称),如果可用,则生成与当前剪贴上下文直接关联的名称列表。例如,foo,bar :: $(typeSplice)将看到[foo,bar],foo = $(exprSplice)将看到[foo],而$(topLevelDecSplice)将看到[]。

(6) 可选添加isTopLevel :: Name -> Q Bool来检测名称是否在顶层绑定(在当前模块中?)。类似这样的东西也可以通过搜索topLevelNames来完成。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接