编译与解释:让或不让

时间:2016-10-17 15:39:16

标签: haskell compilation ghci interpretation

为什么Haskell解释器(GHCI 7.10.3)需要函数定义在let表达式中,但如果函数定义在let表达式中,Haskell编译器(GHC 7.10.3)会抛出解析器错误?

我正在通过“Learn You a Haskell for Great Good!”宝贝的第一个功能是doubleMe:     doubleMe x = x + x

为什么解释器接受这个定义,如果它在let表达式中,否则在输入'='上抛出一个解析错误?同时,如果我正在从文件中编译相同的函数,为什么GHC会抛出一个解析错误,如果函数定义在let表达式中并且如果它不在let表达式中则编译定义?来自Lisp背景,我很惊讶交互式Haskell和文件加载和编译Haskell以不同的方式处理这些定义。

3 个答案:

答案 0 :(得分:4)

这背后的原因是GHCi(在7.10.3中)只在提示时预期

如果这对您来说似乎很惊讶,请记住Lisp和Haskell的评估是非常不同的 - Lisp只是被解释,而Haskell正在被编译。

如您所知,顶级定义不是此列表的一部分。值得庆幸的是,这已在GHCi 8.0.1中得到修复,它现在支持原始顶级函数声明。以下工作(在8.0.1中):

let doubleMe x = x + x

答案 1 :(得分:3)

GHCi解释器命令行将其输入视为do子句中的输入。所以你可以输入:

:module + System.Random
v <- getStdRandom $ randomR (1,10)

:module指令外,这正是do子句中的指示。

同样你可以写

let f x = 2 * x

因为这就是do子句中的含义。

答案 2 :(得分:0)

Modern Lisp实现编译为本机代码,通常默认情况下即使在提示符下输入代码也是如此。 Lisp的提示不仅仅是一个输入命令的地方,它是一个与语言交互的地方,因为Read-Evaluate-Print Loop提供了整个语言。这意味着Lisp将文本读入符号表达式,然后进行评估,打印任何打印输出和任何返回值。例如,

? (defun a-fun () nil)
A-FUN
? (compiled-function-p #'a-fun)
T

Compiled-Function-P Clozure Common Lisp

使用Lisp代码,你可以通过编译和加载文件进入Lisp图像,你也可以通过在REPL输入来输入Lisp图像。所以事实证明我很惊讶,因为我期望GHCi提示符是一个REPL,但正如@Alec描述的那样,并不是因为它不会将文本读入Haskell表达式,然后它会像Lisp那样进行评估。正如@dfeuer所说,问题不在于编译与解释。问题是GHCi的提示提供了与Haskell编译器的有限交互,而不是像Lisp的REPL那样与Haskell本身进行交互。