Compiled vs Interpreted: To Let or Not To Let - haskell

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.

The reasoning behind this is that GHCi (in 7.10.3) expects at the prompt only
commands (type in :h to list the commands available)
declarations (things like data, type, newtype, class, instance, deriving, and foreign but not a regular definition)
imports
expressions (things like 1+1 or let x = 3 in x*x)
I/O Actions / 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

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.

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.

Related

Why does this code not parse without whitespace?

So I am learning Monads and was playing around with the following expression:
[1,2] >>= \x -> ['a','b'] >>= \y -> return (x,y)
The above code produces the result [(1,a),(1,b),(2,a),(2,b)] as expected.
But since I was just experimenting, I got lazy and I entered:
[1,2]>>=\x->['a','b']>>=\y->return (x,y) (same code as above but without white-spaces)
which doesn't seem to work.
I understand that if I properly bracket out this expression as
[1,2]>>=(\x->(['a','b']>>=(\y->return (x,y))))
it will work (better I just put spaces than these monstrous brackets) but I don't get why the expression with white-space works whereas the other one doesn't.
You need spaces to separate identifier names: foo bar is two separate names, whereas foobar (without the space) is just one name.
The same thing happens with operators. Haskell allows arbitrary user-defined operators; if you want to write a function named ??++!?!, then go for it! But you must use spaces to separate operators from one another.
Just as >>= is not the same thing as >> =, so >>=\ isn't the same as >>= \. You could actually define a function named >>=\ if you wanted. But the space lets the Haskell language parser know this is two things, not one.
To fully understand this, you need to look at Chapter 2 of the Haskell Report, particularly section 2.4. The lexeme -> is a reservedop, >>= is not.
For example, does this expression require a space, or spaces?
[1,2]>>=return
[1,2] >>=return

Meaning of single colon in Haskell :t

As far as I've been able to gather, the single colon in Haskell is used in list comprehension. Why then does it show up in the :t command? Also in the :quit command? There isn't any list comprehension being done, is there?
The :t (short for :type) syntax is special to GHCi, and is not part of the Haskell language syntax. This is similar to how the SQLite interpreter accepts .tables as a command, even though this isn't valid a SQL statement. If you type :?, you can see a complete list of all the commands GHCi understands.
As for using the colon in actual Haskell code:
A colon by itself is a list constructor. This is a reserved name, and can never be redefined.
You should know that function names always start lowercase, while constructor names always start uppercase. Well, in a similar way, an infix constructor must start with a colon, whereas a normal infix operator must not start with a colon (but may contain colons elsewhere).
So, for example, "?:?" is a legal operator name, and :?? is a legal constructor operator name.
x ?:? y = ...whatever...
data Foobar = Int :?? Bool

Print function type to console without ghci

Is there a way of printing the function or expression type to the command line in a compiled Haskell program, much like how ghci has :t which prints out the type?
With a Typeable constraint (from Data.Typeable), you can use show . typeOf.

Evaluate buffer in ghci or hugs via Emacs

Using sml-mode in Emacs I have been able to send my buffer contents directly to an inferior SML process using C-c C-b. Now I want to do the same thing only with Haskell. Haskell-mode does not seem to support this, so I'm wondering: What is the right way to go about this with Emacs and Haskell?
While learning SML I've been using C-c C-b almost non-stop to easily evaluate my program as I go, instantly seeing the results of assigning values etc. But if I use C-c C-l in haskell-mode on a saved file containing two lines, let foo = "foo" and let bar = "bar" - I get "parse error (possibly incorrect indentation)"
I think you are making a common rookie mistake, confusing what you can write inside the repl of ghci and what you write in a haskell source file.
All sml interpreters are made in such a way that you can write any top level declaration into the repl, or put in other words: anything you can write in an sml file, you can write into the sml interpreter. Thus you are allowed to write val foo = "bar" into a file and use C-c C-b to load the file and you are allowed to just put in val foo = "bar" into the interpreter.
On the other hand, because of how haskell work, you can write let foo = 42 into ghci, however it is not a valid top level declaration and thus this can't be in a haskell source file (by it self). On the other hand you can have id n = n in a haskell source file and use C-c C-l to load the file, however you can't write this directly into ghci (you will get an error: :1:6: parse error on input '='). The reason for this is that the repl in ghci runs in the IO monad, and thus what ever you write into ghci must be done using the do notation. I can only recommend that you read Interactive evaluation at the prompt from the Using GHCi user guide.
C-c C-b in sml-mode is the exact same thing as C-c C-l in haskell-mode, well atleast conceptually. I don't know that much about the internals of haskell-mode, but in sml-mode C-c C-b executes some sml code in the interpreter, normally the use(...) function. In haskell-mode it seems to just excute the :load "..." ghci command
You can't do that with ghci (or hugs) for the simple reason that you can't write top-level definitions in ghci (or hugs). So even if you manually pasted your file's contents into ghci, all you'd get would be a syntax error.
So loading a file using C-c C-l is the best you can do.

GHCi usage question

I am studying Haskell and use Emacs+Haskell mode as my editor.
After playing some simple expressions in GHCi, I am wondering whether these IDE/editor functionality that exist in Visual Stuido for F#:
Can I send the content in the clipboard into the interpreter? Currently I can only :load the file into the interpreter. This is inconvienent when I gradually write functions in a script file. Like 'Alt+Enter' in visual stuido.
After compiling, I hope to see the signature of the function, e.g.
let double x = x + x
so that I can better understand the type inference mechanism in Haskell.
On Windows, there's WinGHCi, a gui including (poor, but often sufficient) support for copy and paste. Dunno about the command line version.
Use :type double (or the shortcut :t double) to get the type signature of double. There's also :info which applies to values (including functions) as well as types and typeclasses (e.g. :info Bool lists the definition of Bool and all typeclasses it is an instance of) and says where it was defined.
Regarding question 2, to see the inferred type of an expression every time you type one in, you can give inside ghci :set +t . I think you could also put that in a .ghci file, inside your home directory, as described in http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/ghci-dot-files.html .
As far as I know, there is no support for sending the clipoards to the interpreter "out of the box", but it should not take more than couple of lines of elisp. I'd look in the support modes for other languages and copied it from there if I were you.
Regarding the types, you could type C-c C-t or C-c C-i on any symbol in your code, which would trigger ":t <symbol>" and ":i <symbol>" commands in the ghci process
TAIM claims to send selected expressions in vim to ghci(haven't tried it)
I'm not sure about function signatures inside the editor but in ghci its ":t func"
Actually looking at their youtube video it looks like TAIM may be able to select ":t func" in vim and send it to interpreter.

Resources