Reputation: 378
Why does the Haskell interpreter (GHCI 7.10.3) need function definitions to be in a let expression, but the Haskell compiler (GHC 7.10.3) throws a parser error if a function definition is within a let expression?
I'm working through "Learn You a Haskell for Great Good!" Baby's first function is doubleMe: doubleMe x = x + x
Why does the interpreter accept this definition if it is within a let expression and otherwise throw a parse error on input '='? Meanwhile, if I'm compiling the same function from a file, why does GHC throw a parse error if the function definition is within a let expression and compiles the definition if it is not within a let expression? Coming from a Lisp background, I'm surprised that interactive Haskell and file loading and compilation Haskell treats these definitions differently.
Upvotes: 1
Views: 610
Reputation: 378
Modern Lisp implementations compile to native code, often by default even when code is entered at the prompt. Lisp's prompt isn't just a place to enter commands, it's a place to interact with the language because the entire language is made available by the Read-Evaluate-Print Loop. This means that Lisp reads the text into symbolic expressions, which it then evaluates, printing any print output and any returned values. For example,
? (defun a-fun () nil)
A-FUN
? (compiled-function-p #'a-fun)
T
Compiled-Function-P Clozure Common Lisp
With Lisp, code you can enter into the Lisp image by compiling and loading a file you can also enter into the Lisp image by typing it out at the REPL. So it turns out I was surprised because I was expecting the GHCi prompt to be a REPL, but as @Alec describes it's not because it doesn't read text into Haskell expressions that it would then evaluate, as Lisp does. As @dfeuer says, the issue isn't about compilation versus interpretation. The issue is that GHCi's prompt offers limited interaction with a Haskell compiler, rather than interaction with Haskell itself as Lisp's REPL does.
Upvotes: 0
Reputation: 17796
The GHCi interpreter command line treats its input as if it were in a do
clause. So you can type this:
:module + System.Random
v <- getStdRandom $ randomR (1,10)
Apart from the :module
directive this is exactly how it would be in a do
clause.
Likewise you can write
let f x = 2 * x
because that is how it would be in a do
clause.
Upvotes: 3
Reputation: 32319
The reasoning behind this is that GHCi (in 7.10.3) expects at the prompt only
:h
to list the commands available)data
, type
, newtype
, class
, instance
, deriving
, and foreign
but not a regular definition)1+1
or let x = 3 in x*x
)do
statments (things like print "hi"
or x <- getLine
OR let doubleMe x = x + x
)If this seems surprising to you, remember that the evaluation of Lisp and Haskell is very different - Lisp just gets interpretted, while Haskell is being compiled.
As you can tell, top-level definitions are not part of this list. Thankfully this got fixed in GHCi 8.0.1, which now supports raw top-level function declarations. The following works (in 8.0.1):
ghci> doubleMe x = x + x
ghci> doubleMe 1
2
Upvotes: 4