我目前正在阅读实现函数式语言: SPJ的一个教程和我将在这个问题中引用的(子)章节是3.8.7(第136页).
第一个注意事项是,遵循本教程的读者尚未实现ECase表达式的C方案编译(即出现在非严格上下文中的表达式).
提出的解决方案是转换Core程序,以便ECase表达式根本不会出现在非严格的上下文中.具体来说,每次这样的事件都会创建一个新的超级组合器,其中只有一个变量,该变量的主体对应于原始的ECase表达式,并且该事件本身会被对该超级组合器的调用所替换.
下面我将介绍一个(略微修改过的)1的转换示例
t a b = Pack{2,1} ;
f x = Pack{2,2} (case t x 7 6 of
<1> -> 1;
<2> -> 2) Pack{1,0} ;
main = f 3
== transformed into ==>
t a b = Pack{2,1} ;
f x = Pack{2,2} ($Case1 (t x 7 6)) Pack{1,0} ;
$Case1 x = case x of
<1> -> 1;
<2> -> 2 ;
main = f 3
Run Code Online (Sandbox Code Playgroud)
我实现了这个解决方案,它就像魅力一样,就是输出Pack{2,2} 2 Pack{1,0} …
haskell functional-programming compilation language-implementation lazy-evaluation
在GHC的流程中,有一个阶段是将Haskell源代码转换为Core,然后(不一定是紧接的下一步)将Core转换为STG.但是,有一个问题让我无法理解 - 我们什么时候有一个"普通"代码(即纯文本),以及什么东西真的存在于内存中,比如抽象语法树(ASTs)?
为了使我的问题更精确,我将它分成几部分:
1)在解析Haskell源文件阶段时,我们是否立即构建了Core语言的AST?如果没有,那么在我看来,我们必须构建完整Haskell的AST(这似乎很奇怪),然后将它们转换为Core的AST,或者首先在Core中对它们进行文本表示,然后再次调用解析来获取Core的AST.
2)几乎相同的问题适用于Core to STG转换(但在这种情况下,我认为我可以假设我们拥有的是Core的AST - 正确吗?)
compiler-construction haskell compilation abstract-syntax-tree ghc
考虑下面的OCaml代码:
type mytype = My : 'a list * 'a -> mytype
let rec foo : int -> mytype =
fun n -> if n < 0 then My([], 2)
else let My(xs, y) = foo (n - 1)
in My(3::xs, y)
Run Code Online (Sandbox Code Playgroud)
OCaml解释器在最后一行给出了一个错误foo,说:
此表达式具有类型#1列表,但是期望类型为int list的表达式
类型#1与int类型不兼容
我可以通过添加类型参数来mytype使代码工作,这样就可以了
type _ mytype = My : 'a list * 'a -> 'a mytype
let rec foo : int -> 'a mytype =
...
Run Code Online (Sandbox Code Playgroud)
但是,让我说我真的不想改变它的定义mytype.我可以写foo,假设我想保留该功能(由非工作代码直观地理解)行为?
此外,有人可以解释问题的根源,即为什么初始代码不进行类型检查?