首页 > 解决方案 > 获取模块导出的列表

问题描述

类似的问题(有没有办法在 GHCI 中查看模块中的函数列表?),虽然不是我寻求的结果。

有没有办法获取模块导出的内容列表?

当然,在 GHCi 中,您可以导入它,然后键入Some.Module.,点击选项卡以自动完成,它会显示我所寻找的内容。但我想捕捉那些东西。粗略地说,String -> [String].

目的?假设我有一个带有裸import Some.Module. Some.Module问题:该文件属于什么?一种简单的方法是输出模块导出的列表,将其提供给grep并返回竞争者,而无需在 GHCi 中加载该源文件(可能很复杂或不可能)。一切都变得清晰了很多。

如果有更聪明的方法,我在听。我听说过涉及GOA和的解决方案lambdabot。不知道是否适用或如何利用它。

标签: haskell

解决方案


正如@HTNW 在评论中提到的那样,如果您可以ghc在实际文件上运行,则可以使用-ddump-minimal-imports. 否则,如果您想实际获取另一个模块的导出列表,假设您正在使用 GHC,那么最简单的方法可能是查看.hi 接口文件ghc一旦您知道了接口文件的路径,就有一些内置支持打印接口文件的人类可读表示,但正如 wiki 页面所指出的那样“这种文本格式不是专门为机器解析而设计的”。您还可以通过 GHC API 访问您可能需要的信息。下面是一个做类似事情的小例子。

我们从一堆随机导入开始,用于从 GHC api 执行 IO 和:

import Control.Monad.IO.Class
import System.IO
import System.Environment

import GHC
import GHC.Paths (libdir)
import DynFlags
import Outputable
import Name
import Pretty (Mode(..))

摆脱官僚主义,main首先启动 GHC Monad:

main :: IO ()
main = defaultErrorHandler defaultFatalMessager defaultFlushOut $ do
  runGhc (Just libdir) $ do

我们实际上并没有生成任何代码,因此我们可以hscTarget = HscNothingDynFlags设置样板中进行设置:

    dflags <- getSessionDynFlags
    let dflags' = dflags { hscTarget = HscNothing }
    setSessionDynFlags dflags'

这样我们就可以从包数据库中找到我们想要的模块(使用第一个命令行参数作为名称):

    mn <- head <$> (liftIO $ getArgs)
    m <- lookupModule (mkModuleName mn) Nothing

我们可以getModuleInfo用来获取模块信息结构:

    mmi <- getModuleInfo m
    case mmi of
      Nothing -> liftIO $ putStrLn "Could not find module interface"

如果我们确实找到了接口,我们需要的一切都在modInfoExports. 如果我们需要更多,我们还可以获得实际的ModIface

      Just mi -> mapM_ (printExport dflags') (modInfoExports mi)

实际上打印输出有点乏味,因为它需要使用Names; 一个简单的例子printExport可能只使用了漂亮的打印功能,但这些功能更多地用于打印人类可读的输出而不是机器可读的输出:

printExport :: DynFlags -> Name -> Ghc ()
printExport dflags n =
  liftIO $ printSDocLn PageMode dflags stdout (defaultUserStyle dflags)
         $ pprNameUnqualified n

推荐阅读