Skip to content

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:

GHCi
>>> x = 5
>>> x
5
>>> 2 * x
10

Function definitions are the same. We've seen this definition already:

GHCi
>>> double x = 2 * x
>>> double 20
40

Or maybe a function to compute the length of a 2-d vector:

GHCi
>>> 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.

GHCi
>>> :{
  | 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.