我正在寻找如何将简单的Haskell程序(没有导入的库,只是数据类型和纯函数)转换为无类型lambda演算的术语。一种有希望的方法似乎是使用GHC API将程序编译成GHC core,然后可以将其转换为无类型的lambda演算。
如何使用GHC API加载Haskell程序并将其编译为Core?
答案 0 :(得分:5)
来自ghc docs中的GHC
module documentation:
compileToCoreModule :: GhcMonad m => FilePath -> m CoreModule
这是访问与a对应的Core绑定的方法 模块。
compileToCore
解析,类型检查和desugars模块, 然后返回生成的Core模块(由模块名称组成, 如果成功,则输入类型声明和函数声明。
compileToCoreSimplified :: GhcMonad m => FilePath -> m CoreModule
与
compileToCoreModule
类似,但调用简化器,以便返回 简化和整理Core。
我通过浏览GHC
模块列表,注意到Desugar
模块,在deSugar
的结果中注意到ModGuts
,下载了所有文档,并在文本中搜索ModGuts
。
我们的示例将编译一个简单的模块,以便我们可以看到核心的样子。它使用ghc-paths来提供ghc libs目录的位置。核心将由包含CoreModule
列表的CoreBind
s在内存中表示。我们无法直接转储AST,因为Show
中描述的AST没有CoreSyn
个实例,但Outputable
的{{1}}实例会很漂亮 - 打印核心,以便我们可以看到我们编译为核心。
CoreModule
import GHC
import DynFlags
import Outputable (Outputable, showPpr)
import qualified GHC.Paths as Paths
import Data.Functor
负责编译核心模块所需的所有设置,没有runGhc'
s且没有import
。我们用NoLink
完全关闭链接器并告诉编译器不要生成HscNothing
。
TemplateHaskell
将模块编译为核心包括使用guessTarget
和addTarget
设置目标,可选择使用load
加载依赖项,使用depanel
构建模块图,{{1在模块图中使用正确的ModSummary
,使用parseModule
解析模块,使用typecheckModule
输入格式,使用desugarModule
对其进行去除,并将其转换为{{3}来自runGhc' :: Ghc a -> IO a
runGhc' ga = do
runGhc (Just Paths.libdir) $ do
dflags <- getDynFlags
let dflags2 = dflags { ghcLink = NoLink
, hscTarget = HscNothing
}
setSessionDynFlags dflags2
ga
实例的ModGuts
获取desugarring的结果,并从find
中提取核心。所有这些都被coreModule
包裹在一个很好的包中。
DesugaredMod
我们的整个示例程序将使用compileToCoreModule
输出核心。
ModGuts
编译上面的示例需要compileExample :: Ghc CoreModule
compileExample = compileToCoreModule "prettyPrint2dList.hs"
标志来公开通常隐藏的ghc api包。
我们编译到核心的示例模块showPpr' :: (Functor m, Outputable a, HasDynFlags m) => a -> m String
showPpr' a = (flip showPpr) a <$> getDynFlags
main = runGhc' (compileExample >>= showPpr') >>= putStrLn
包含一个数据类型和一些使用前奏函数的代码。
-package ghc
这产生了大量漂亮的印刷核心。
"prettyPrint2dList.hs"