Should I avoid using interactive mode? - haskell

Haskell newbie here. I use ghci to implement a baby quicksort algorithm [1] as follows:
Prelude> quicksort (firstx:xs) = quicksort[x|x<-xs, x<firstx] ++ [firstx] ++ quicksort[x|x<-xs, not(x<firstx)]
Prelude> quicksort [] = []
The command quicksort [1,2,3] then gives an error:
*** Exception: :8:1-17: Non-exhaustive patterns in function quicksort
However, typing the exact same thing in an quicksort.hs file and running $ ghci quicksort.hs do not yield such an error.
Question
What makes the difference? Is it a rule of thumb that one should avoid using interactive mode?
Reference
[1] Rex Page. Two Dozen Short Lessons in Haskell

It's generally easier to define a multi-line function in a file and then load :l <module> or reload :r, but I do sometimes declare a multi-line function directly in GHCi starting with :{ and :}:
:{
quicksort (firstx:xs) = quicksort[x|x<-xs, x<firstx] ++ [firstx] ++ quicksort[x|x<-xs, not(x<firstx)]
quicksort [] = []
:}
:h is useful if you forget any commands while in GHCi.
Edit: forget to address the second part of your question.
Is it a rule of thumb that one should avoid using interactive mode?
Interactive mode is a great tool and I miss it in other ecosystems like ReasonML that do not have one. There is no reason to avoid it. Just remember to copy your code over if you come up with some that you want to keep.

Related

Can anything done in a Haskell script be reproduced in a GHCi session?

I want to run the function
act :: IO(Char, Char)
act = do x <- getChar
getChar
y <- getChar
return (x,y)
interactively in a GHCi session. I've seen elsewhere that you can define a function in a session by using the semi-colon to replace a line-break. However, when I write
act :: IO(Char, Char); act = do x <- getChar; getChar; y <- getChar; return (x,y)
it doesn't compile, saying
parse error on input ‘;’
I've elsewhere seen that :{ ... }: can be used for multiple line commands, but typing
:{ act :: IO(Char, Char)
and then hitting enter causes an error--perhaps I'm misunderstanding how to use them.
Besides just getting this particular case to work, is there a generic way of taking code that would run in a Haskell script and making it run in an interactive session?
You can't just insert semicolons to replace each line break. Doing stuff on one line means opting out of the layout rule, so you have to insert your own semicolons and braces. This means you need to know where those braces and semicolons would be required without the layout rule. For this case in particular, each do block needs braces around the whole block, and semicolons between each operation. The layout rule normally inserts these for you based on indentation.
So to write this specific example on one line, you can do this:
let act :: IO(Char, Char); act = do {x <- getChar; getChar; y <- getChar; return (x,y)}
On a new enough version of ghci you can omit the let as well.
For simple enough do blocks you might even get away with omitting the braces. In your example there's only one place the { and } could possibly go, and so GHCI inserts them even when you do everything on one line. But for an expression with multiple do blocks or other multiline constructs, you will need to insert them explicitly if you want them on one line.
On the broader question:
Besides just getting this particular case to work, is there a generic way of taking code that would run in a Haskell script and making it run in an interactive session?
The closest thing I know of is using the multiline delimiters, ":{ and :} (each on a single line of its own)". They can handle almost anything you can throw at them. They can't handle imports (GHCi does support the full import syntax, but each import must be on its own in a line) and pragmas (the only alternative is :set, which also need a line all of its own), which means you can't help but separate them from the rest of the code and enter them beforehand.
(You can always save the code somewhere and load the file with :l, and that will often turn out to be the more convenient option. Still, I have a soft spot for :{ and :} -- if I want no more than trying out half a dozen lines of impromptu code with no context, I tend to open a text editor window, write the little snippet and paste it directly in GHCi.)

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

Compiled vs Interpreted: To Let or Not To Let

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.

Cannot enter multiline statements in GHCi [duplicate]

This question already has answers here:
Multi-line commands in GHCi
(5 answers)
Closed 9 years ago.
let x=1
y=2
z=3
does not work in GHCi, forcing me to use let {x=1;y=2;y=3} instead. How can I fix this problem?
The documentation says:
GHCi also has a multiline mode, enabled by :set +m, in which GHCi detects automatically when the current statement is unfinished and allows further lines to be added. A multi-line input is terminated with an empty line.
The multiline mode makes GHCi behave much like e.g. the Python interpreter:
Prelude> :set +m
Prelude> let x = 1
Prelude| y = 2
Prelude| z = 3
Prelude|
Prelude> (x, y, z)
(1,2,3)
This hidden gem is wonderful for playing with readable code!
If you want this to be the default behaviour, you can create a .ghci file in your home directory with a line saying :set +m. (Now that this came up, I actually did so.)

Find inferred type for local function

Is there a way in ghci (or ghc) to find what the inferred type of a local function is?
E.g. if I have a function
f l = map f' l
where f' = (+1)
is there a :t-like way in ghci to see what the inferred type for f' is?
Indeed there is, which I learned about thanks to hammar's awesome answere here. Here's the short version:
Prelude> :l /tmp/foo.hs
[1 of 1] Compiling Main ( /tmp/foo.hs, interpreted )
Ok, modules loaded: Main.
*Main> :break f
Breakpoint 0 activated at /tmp/foo.hs:(1,1)-(2,18)
*Main> f [1..10]
Stopped at /tmp/foo.hs:(1,1)-(2,18)
_result :: [b] = _
[/tmp/foo.hs:(1,1)-(2,18)] *Main> :step
Stopped at /tmp/foo.hs:1:7-14
_result :: [b] = _
f' :: b -> b = _
l :: [b] = _
[/tmp/foo.hs:1:7-14] *Main> :t f'
f' :: b -> b
I don't know of any way of doing it from GHCi.
However, if you're using an editor like Emacs or Vim, you can try ghc-mod. This is an external tool that plugs into an editor and gives you some IDE-like functionality for Haskell programs, including the ability to get the type of an arbitrary expression, including a local definition.
In Emacs, you would use C-c C-t to find the type of an expression.
If you're not using Emacs or Vim, you could probably wrap ghc-mod as a GHCi extension or something, but I think that would be somewhat awkward. I can't imagine a good way to do it without having an editor-like UI. However, ghc-mod itself is just a standalone command-line tool, so it's easy to work with. If you can think of a good user interface for it that's independent of an existing text editor, go for it!
Of course, if you're not using Emacs or Vim, you probably should :P.
Try hdevtools, it's quite fast and easy to use, though there's only integration for Vim.

Resources