如何将Haskell编译成无类型的lambda演算(或GHC核心)?

时间:2014-12-24 10:05:51

标签: haskell lambda-calculus ghc-api

我正在寻找如何将简单的Haskell程序(没有导入的库,只是数据类型和纯函数)转换为无类型lambda演算的术语。一种有希望的方法似乎是使用GHC API将程序编译成GHC core,然后可以将其转换为无类型的lambda演算。

如何使用GHC API加载Haskell程序并将其编译为Core?

1 个答案:

答案 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列表的CoreBinds在内存中表示。我们无法直接转储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

将模块编译为核心包括使用guessTargetaddTarget设置目标,可选择使用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"