来自ghc文档中的ghc
模块文档:
CompileTocoRemodule::GhcMonad m=>FilePath->m CoRemodule
这是访问与模块相对应的核心绑定的方法。CompileToCore
对模块进行解析、typechecks和desugars,如果成功,则返回结果核心模块(包括模块名称、类型声明和函数声明)。
我们的示例将编译一个简单的模块,这样我们就可以看到核心是什么样子的。它使用ghc-paths提供ghc libs目录的位置。内核将在内存中由corremodule
表示,该coreRemodule包含coreRebind
的列表。我们不能直接转储AST,因为没有coresyn
中描述的AST的show
实例,但是corremodule
的outputable
实例将漂亮地打印内核,这样我们就可以看到编译为内核了。
import GHC
import DynFlags
import Outputable (Outputable, showPpr)
import qualified GHC.Paths as Paths
import Data.Functor
runghc'
负责编译一个没有import
和没有templatehaskell
的模块所需的所有设置。我们使用nolink
完全关闭链接器,并告诉编译器使用hscnothing
生成任何内容。
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
将模块编译为核心包括使用guesstarget
和addtarget
设置目标,使用load
可选地加载依赖项,使用depanel
构建模块图,使用depanel
查找在模块图中找到正确的modsummary
解析模块,使用parsemodule
类型检查模块,使用typecheckmodule
desugarmodule解析环,并从modguts
中提取核心。所有这些都由CompileTocoRemodule
封装在一个很好的包中。
compileExample :: Ghc CoreModule
compileExample = compileToCoreModule "prettyPrint2dList.hs"
我们的整个示例程序将使用showppr
输出内核。
showPpr' :: (Functor m, Outputable a, HasDynFlags m) => a -> m String
showPpr' a = (flip showPpr) a <$> getDynFlags
main = runGhc' (compileExample >>= showPpr') >>= putStrLn
编译上面的示例需要-package ghc
标志来公开通常隐藏的ghc api包。
我们将编译为核心的示例模块“prettyprint2dlist.hs”
包含一个数据类型和一些使用前奏中函数的代码。
data X = Y | Z
deriving (Eq, Show)
type R = [X]
type W = [R]
example = map (\x -> take x (cycle [Y, Z])) [0..]
main = undefined
%module main:Main (Safe-Inferred) [01D :-> Identifier `:Main.main',
a1f2 :-> Identifier `$c==', a1f5 :-> Identifier `$c/=',
a1fb :-> Identifier `$cshowsPrec', a1fh :-> Identifier `$cshow',
a1fk :-> Identifier `$cshowList',
r0 :-> Identifier `Main.$fShowX', r1 :-> Identifier `Main.$fEqX',
r2 :-> Type constructor `Main.R',
r3 :-> Type constructor `Main.X', r4 :-> Identifier `Main.main',
rqS :-> Type constructor `Main.W',
rrS :-> Data constructor `Main.Y', rrV :-> Identifier `Main.Y',
rrW :-> Data constructor `Main.Z', rrX :-> Identifier `Main.Z',
rL2 :-> Identifier `Main.example']
Main.example :: [[Main.X]]
[LclIdX, Str=DmdType]
Main.example =
GHC.Base.map
@ GHC.Types.Int
@ [Main.X]
(\ (x :: GHC.Types.Int) ->
GHC.List.take
@ Main.X
x
(GHC.List.cycle
@ Main.X
(GHC.Types.:
@ Main.X
Main.Y
(GHC.Types.: @ Main.X Main.Z (GHC.Types.[] @ Main.X)))))
(GHC.Enum.enumFrom
@ GHC.Types.Int GHC.Enum.$fEnumInt (GHC.Types.I# 0))
Main.main :: forall t. t
[LclIdX, Str=DmdType]
Main.main = GHC.Err.undefined
$cshowsPrec :: GHC.Types.Int -> Main.X -> GHC.Show.ShowS
[LclId, Str=DmdType]
$cshowsPrec =
\ _ [Occ=Dead] (ds_d1gG :: Main.X) ->
case ds_d1gG of _ [Occ=Dead] {
Main.Y ->
GHC.Show.showString
(GHC.Types.:
@ GHC.Types.Char
(GHC.Types.C# 'Y')
(GHC.Types.[] @ GHC.Types.Char));
Main.Z ->
GHC.Show.showString
(GHC.Types.:
@ GHC.Types.Char
(GHC.Types.C# 'Z')
(GHC.Types.[] @ GHC.Types.Char))
}
Main.$fShowX [InlPrag=[ALWAYS] CONLIKE] :: GHC.Show.Show Main.X
[LclIdX[DFunId],
Str=DmdType,
Unf=DFun: \ ->
GHC.Show.D:Show TYPE Main.X $cshowsPrec $cshow $cshowList]
Main.$fShowX =
GHC.Show.D:Show @ Main.X $cshowsPrec $cshow $cshowList;
$cshowList [Occ=LoopBreaker] :: [Main.X] -> GHC.Show.ShowS
[LclId, Str=DmdType]
$cshowList =
GHC.Show.showList__
@ Main.X
(GHC.Show.showsPrec @ Main.X Main.$fShowX (GHC.Types.I# 0));
$cshow [Occ=LoopBreaker] :: Main.X -> GHC.Base.String
[LclId, Str=DmdType]
$cshow = GHC.Show.$dmshow @ Main.X Main.$fShowX;
$c== :: Main.X -> Main.X -> GHC.Types.Bool
[LclId, Str=DmdType]
$c== =
\ (ds_d1gB :: Main.X) (ds_d1gC :: Main.X) ->
let {
fail_d1gD :: GHC.Prim.Void# -> GHC.Types.Bool
[LclId, Str=DmdType]
fail_d1gD = \ _ [Occ=Dead, OS=OneShot] -> GHC.Types.False } in
case ds_d1gB of _ [Occ=Dead] {
Main.Y ->
case ds_d1gC of _ [Occ=Dead] {
__DEFAULT -> fail_d1gD GHC.Prim.void#;
Main.Y -> GHC.Types.True
};
Main.Z ->
case ds_d1gC of _ [Occ=Dead] {
__DEFAULT -> fail_d1gD GHC.Prim.void#;
Main.Z -> GHC.Types.True
}
}
Main.$fEqX [InlPrag=[ALWAYS] CONLIKE] :: GHC.Classes.Eq Main.X
[LclIdX[DFunId],
Str=DmdType,
Unf=DFun: \ -> GHC.Classes.D:Eq TYPE Main.X $c== $c/=]
Main.$fEqX = GHC.Classes.D:Eq @ Main.X $c== $c/=;
$c/= [Occ=LoopBreaker] :: Main.X -> Main.X -> GHC.Types.Bool
[LclId, Str=DmdType]
$c/= =
\ (a :: Main.X) (b :: Main.X) ->
GHC.Classes.not (GHC.Classes.== @ Main.X Main.$fEqX a b);
:Main.main :: GHC.Types.IO GHC.Prim.Any
[LclIdX, Str=DmdType]
:Main.main =
GHC.TopHandler.runMainIO
@ GHC.Prim.Any (Main.main @ (GHC.Types.IO GHC.Prim.Any))
我在Haskell编程中的冒险并不都是史诗般的。我正在实现简单的Lambda演算,我很高兴完成了、以及,希望它们是正确的。剩下的是,就像红色框中定义的那样(在下图中),我正在为此寻找指导。 如果我说错了请指正, (1)但是我发现返回给定变量的类型。Haskell中的什么构造返回?我知道在中是,但我正在寻找一个在下工作的。 (3)对于(T-APP)和(T-ABS),我假设我分别对和应用程序应用了替换
部分答案可能来自领域理论。如果我理解正确的话,的元素并不全是集合论函数(根据康托定理,这些函数比大),而只是连续函数。如果是,定义这种连续性的拓扑是什么?为什么类型的Haskell术语对它是连续的?
其中是用于定义替换的函数。 然而,当我试图使用beta约简来约简表达式时,我得到了一个非穷举模式错误,我不明白为什么。我能做的修复它是在底部添加一个额外的大小写,如下所示: 但是,如果我这样做了,那么lambda表达式根本不会被缩减,这意味着函数的输入和输出是相同的。 如果使用第一个函数而不添加最后一个大小写,则为非穷尽模式 或完全相同的表达式App(ABS1(ABS2(VAR1)))(VAR3)
GHC(Glasgow Haskell compiler)是 Haskell 最顶级最好的编程套件,包括一个优化的编译器,生成各种平台的优秀代码,同时还有个交互式系统,让用户使用起来更简单方便,能使用 Haskell 进行快速的开发。它支持多种语言的扩展,包括并发,异常和其他语言的接口(C 语言等等)。
我的第二个问题是,我知道有许多可用于Java和Python等语言的基准测试,但我试图为lambda演算寻找类似的基准测试,但没有找到任何东西。是否有机会为STLC或非类型化的lambda演算提供基准测试?
问题内容: 它可以有效地编译到哪一个? 或类似的东西 那么它会替代(某种内联),还是实际上创建一个匿名类? 问题答案: VM决定如何实现lambda,而不是编译器。 请参阅《 Lambda表达式的翻译》中的部分。 我们没有生成字节码来创建实现lambda表达式的对象(例如,调用内部类的构造函数),而是描述了构造lambda的方法,并将实际构造委托给语言运行时。该配方被编码在invokedynami