Defining Values and Functions
A definition in Haskell is an equation, such as x = 5
. This defines x
to
be equal to 5
, which you can verify by inspecting the value of x
afterwards:
>>> x = 5
>>> x
5
>>> 2 * x
10
Function definitions are the same. We've seen this definition already:
>>> double x = 2 * x
>>> double 20
40
Or maybe a function to compute the length of a 2-d vector:
>>> veclen (x, y) = sqrt (x * x + y * y)
>>> veclen (3, 4)
5.0
We don't know the types of control flow constructs yet to define much more interesting functions, but as a glimpse of how to define functions in GHCi, this should suffice.
Multi-Line Definitions
As discussed before, code blocks are delimited using indentation in Haskell.
As a result, most interesting definitions span multiple lines. In a Haskell
source code file, this is not a problem. In GHCi, the moment you press Enter
at the prompt, GHCi assumes that this is the whole expression or definition to
be evaluated. If it is incomplete, you will get a syntax error. GHCi will not
allow you to complete it by entering more lines. As an interactive
environment, GHCi would be pretty limited if it didn't have a way to work
around this behaviour, and there is. The GHCi command :{
starts a multi-line
expression or definition. After you enter this command, GHCi lets you enter as
many lines as you want. Only once you enter the closing command :}
will it
take the entire block of lines and evaluate them.
Here is an implementation of Merge Sort in Haskell, all typed in at the GHCi prompt. You do not need to understand this definition yet. What's important here is that it spans multiple lines.
>>> :{
| mergeSort [] = []
| mergeSort xs = mergeInPairs [[x] | x <- xs]
|
| mergeInPairs [xs] = xs
| mergeInPairs xss = mergeInPairs $ mergePairs xss
|
| mergePairs (xs:ys:xss) = merge xs ys : mergePairs xss
| mergePairs xss = xss
|
| merge xs [] = xs
| merge [] ys = ys
| merge xs@(x:xs') ys@(y:ys')
| | x <= y = x : merge xs' ys
| | otherwise = y : merge xs ys'
| :}
>>> mergeSort [5,8,12,1,3,2,30,1,9]
[1,1,2,3,5,8,9,12,30]
This is a pretty extreme example. If you make a mistake in one of the many lines
entered here, GHCi will give you an error message and then you'll have to repeat
all of the lines. This gets tedious quickly, and editing the function
definition in a text file and loading the file into GHCi, as explained next, is
the better option. For short multi-line definitions, the :{ ... :}
command is
quite handy though.
As an aside, note that the lines between :{
and :}
in the previous example
are indented two spaces and start with |
. That's because I have the line
:set prompt-cont " | "
in my ~/.ghci
file, as explained here.