The Complete Magazine on Open Source

Getting Started with Haskell on Emacs

, / 109 0

EmacsEmacs is a popular text editor that can be extended and customised. Haskell is a statically typed, functional programming language. Haskell-mode is an Emacs major mode that provides support to write and use Haskell programs. This article explains interesting features and tips on using Haskell-mode with GNU Emacs.

You can install Haskell-mode using your distribution package manager. For example, on Fedora you can use:

$ sudo yum install emacs-haskell-mode

You can enter Haskell-mode when opening a Haskell source file that has an extension .hs, or it can be started within Emacs using:

M-x haskell-mode

On the modeline, you will now see -(Haskell)’, indicating that the Haskell mode has been activated. You can enter the indent mode using:

M-x haskell-indent-mode

The modeline will now show (Haskell Ind).


To load a Haskell source file into the interpreter, use C-c C-l. It will create a new buffer, load the module in the current buffer and give a prompt to work with. Consider the following Square.hs program:

square :: Int -> int
square x = x * x

Opening a Square.hs file in an Emacs buffer, and running C-c C-l will produce the following in a new buffer:

GHCi, version 7.0.4: :? for help.
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :load "/home/guest/Square.hs"
[1 of 1] Compiling Main ( /home/guest/Square.hs, interpreted )
Ok, modules loaded: Main.

If you have multiple buffers opened within Emacs, you can directly switch from the (Haskell) mode buffer to the Haskell interpreter using C-c C-z.

The equal to (=) sign can be inserted, and the function type can be neatly aligned with the C-c C-= key stroke. If you type the following function:

volume :: Int -> Int -> Int
volume x

…and keep the cursor after ‘x’ and type C-c C-=, the equal to sign is inserted, and the code gets neatly aligned:

volume   :: Int -> Int -> Int
volume x =

In the following code snippet, after ‘y’ , if you hit Return followed by C-c C-/, a guard symbol is inserted:

max :: (Ord a) => a -> a -> a
max x y|

After inserting the second guard in the above example, the otherwise keyword can be inserted and the code is aligned using C-c C-o:

max :: (Ord a) => a -> a -> a
max x y
| x > y     = x
| otherwise =

The ‘where’ clause is produced using C-c C-w. In the following example, pressing return after ‘r’, and using

 C-c C-w inserts the 'where' clause:

circleArea :: Float -> Float
circleArea r = pi * r * r

You can insert the type annotation for a function using C-u C-c C-t. Consider the sphereVolume function:

sphereVolume r = 4 / 3 * pi * r * r * r
where pi = 3.1412

Placing the cursor on ‘sphereVolume’ and typing C-u C-c C-t produces the following:

sphereVolume :: Fractional a => a -> a
sphereVolume r = 4 / 3 * pi * r * r * r
where pi = 3.1412


There are a number of shortcut commands that are useful for indentation. Let’s suppose you have the following function with the cursor position indicated by ‘_’:

greeting :: String -> String
greeting x = "Hello" ++ x ++

Hitting Tab will take you through the different possible positions for inserting code. When you press Tab for the first time, the cursor will move under ‘Hello’; if you wish to complete the string concatenation (++), issue the following code:

greeting :: String -> String
greeting x = "Hello" ++ x ++

Hitting Tab again prepends ‘greeting’ and the cursor will be placed under ‘x’ for you to add another test condition, as follows:

greeting :: String -> String
greeting x = "Hello" ++ x ++
greeting _

Hitting Tab yet again will move the cursor to the first column if you want to add any text:

greeting :: String -> String
greeting x = "Hello" ++ x ++

As you keep hitting Tab again and again, the above sequence will repeat. Comments in Haskell begin with ‘- -‘.

one -- 1
two -- 2
three -- 3
four -- 4
five -- 5
six -- 6
seven -- 7

After marking the above region, use M-x align-regexp followed by ‘- -‘ for the regexp, and the comments will be aligned:

one    -- 1
two    -- 2
three  -- 3
four      -- 4
five      -- 5
six      -- 6
seven      -- 7

C-c C-. helps align the code neatly. Consider the Area.hs program:

area :: Int -> Int -> Int
area breadth height = breadth * height

After marking the above program, and using C-c C-., the code becomes:

area                      :: Int -> Int -> Int
area breadth height = breadth * height


To know the Haskell-mode version, use M-x haskell-version. As an example:

Using Haskell-mode version v2.8.0,

C-c C-i on a symbol will prompt for getting information about the symbol. For example, ‘Show info of (default Int):lists the following:

data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in GHC.Types
instance Bounded Int -- Defined in GHC.Enum
instance Enum Int -- Defined in GHC.Enum
instance Eq Int -- Defined in GHC.Base
instance Integral Int -- Defined in GHC.Real
instance Num Int -- Defined in GHC.Num
instance Ord Int -- Defined in GHC.Base
instance Read Int -- Defined in GHC.Read
instance Real Int -- Defined in GHC.Real
instance Show Int -- Defined in GHC.Show

C-c C-t will obtain the type of the symbol with the prompt Show type of (default pi):. For example:

pi :: Floating a => a

C-c TAB on a symbol returns its definition at the interpreter prompt, as follows:

*Main> :info sphereVolume
sphereVolume :: Fractional a => a -> a
-- Defined at /home/guest/Sphere.hs:1:1-12

To find Haddock information for a symbol, you can use C-c C-d. Searching for ‘Float’, for example, opens up the following file: ///usr/share/doc/ghc/html/libraries/ghcprim- on Fedora.

To use the Hayoo search engine, you can use M-x haskell-hayoo. It will prompt with:

Hayoo query:

The query responses are shown in a browser. Similarly, the Hoogle engine can be queried using M-x haskell-hoogle. If you searched for ‘show’, it will open the URL with the search results.
Files ending with .lhs are literate Haskell programs. You can use the Richard Bird style to separate text and code as follows:

Insert blank line before the code

> quicksort :: Ord a => [a] -> [a]
> quicksort []     = []
> quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
>   where
>       lesser = filter (< p) xs
>       greater = filter (>= p) xs

Insert blank line after the code

The modeline will indicate that you are in the (LitHaskell/bird) minor mode. The hasktag package needs to be installed to help generate TAGS file for source files. For example:

$ hasktags Test.hs

It will create both tags and TAGS files. You can use M-. in the Haskell buffer to search for a tag.

HLint is a tool that provides suggestions to improve Haskell programs. C-c C-v helps to run hlint on a buffer. Make sure you have the tool installed on your system before using it. For example, running C-c C-v on the above literate quicksort Haskell program suggests:

-*- mode: compilation; default-directory: "~/" -*-
Compilation started at Thu Jun 6 21:31:54
hlint QuickSort.lhs
QuickSort.lhs:6:22: Warning: Redundant bracket
(quicksort lesser) ++ [p] ++ (quicksort greater)
Why not:
quicksort lesser ++ [p] ++ (quicksort greater)
QuickSort.lhs:6:44: Warning: Redundant bracket
[p] ++ (quicksort greater)
Why not:
[p] ++ quicksort greater


[1]    Haskell.
[2]    GNU Emacs.
[3]    Haskell mode 2.8.
[4]    Hasktag.
[5]    HLint.