Usage of Emacs front-end

Key bindings

M-C-i
Completes a name of keyword, module, class, function, types, language extensions, GHC flags, etc.
M-/
Completes a name of local symbol.
M-t
Inserts template. In the beginning of a buffer, "module Foo where" is inserted. On the function without signature, inferred type is inserted. On a symbol "foo" without definition, "foo = undefined" is inserted or a proper module is imported. C-uM-t inserts a hole in this case. On a variable, the case is split. When checking with hlint, original code is replaced with hlint's suggestion if possible.
M-C-d
Browses the local document with your browser. On a module import line, the document of the module is browsed. On a function or type, its document is browsed.
C-uM-C-d
Browses the Hackage document of the module with your browser.
M-C-m
Loads information of symbols for modules in the current buffer. If you add a new line to import a module, type this. The idle timer executes this command anyway.
C-cC-h
Query somthing at the cursor for hoogle.
C-xC-s
Saves the buffer if necessary and runs syntax check.
C-cC-c
Toggle GHC and Hlint for syntax check. GHC is used for initial time.
M-n
Goes to the next warning or error.
M-p
Goes to the previous warning or error.
M-?
Displays the warning/error message in the current line.
C-cC-i
Displays the info of this expression in another window.
C-cC-t
Displays the type of this expression in the minibuffer. Type C-cC-t multiple time to enlarge the expression.
C-cC-a
Selects one of possible cases.
C-cC-f
Replaces a hole with user-typed functions followed by holes.
C-cC-e
Displays the expanded Template Haskell.
C-cC-m
Insert "import Module" for the function at the cursor.
M-s
Sort and merge import statements in the region.
C-cC-j
In the beginning of the buffer, errors of other files are displayed. Typing C-cC-j on the errors jumps to the fist file of the error sources.
C-cC-k
Kill the ghc-modi subprocess for this project. If you install dependency packages, this command should be executed to reflect that change.
C-c<
Make the indentation of the region shallower.
C-c>
Make the indentation of the region deeper.

Resolving import hell

Here is an example story not to type "import Foo" when you write a Haskell program.

Type the following signature. Note that "ByteString" can be completed with M-C-i.

foo :: [ByteString] -> [ByteString] -> [ByteString]

C-xC-s highlights the signature. Typing M-t on the line results in:

import Data.ByteString (ByteString)

foo :: [ByteString] -> [ByteString] -> [ByteString]
foo = undefined

Type M-C-m to load symbols of Data.ByteString. Then edit the body of "foo". Note that "append" can be completed with M-C-i.

import Data.ByteString (ByteString)

foo :: [ByteString] -> [ByteString] -> [ByteString]
foo bs1 bs2 = B.append <$> bs1 <*> bs2

C-xC-s highlights the body. Type M-t to get:

import Data.ByteString (ByteString)
import Control.Applicative ((<*>))
import Control.Applicative ((<$>))
import qualified Data.ByteString as B

foo :: [ByteString] -> [ByteString] -> [ByteString]
foo bs1 bs2 = B.append <$> bs1 <*> bs2

Now select a region for import statements (for instance, move the cursor, type C-SPC, and move the cursor) then type M-s.

import Control.Applicative ((<$>), (<*>))
import Data.ByteString (ByteString)
import qualified Data.ByteString as B

foo :: [ByteString] -> [ByteString] -> [ByteString]
foo bs1 bs2 = B.append <$> bs1 <*> bs2

Type holes

Consider the following broken example:

foo :: [a -> a] -> a -> a
foo xs = foldr bar id xs
  where
    bar = (:)

C-xC-s highlights the 2nd line. C-c? displays the following:

Couldn't match type `[a -> a]' with `a -> a'
Expected type: (a -> a) -> (a -> a) -> a -> a
  Actual type: (a -> a) -> [a -> a] -> [a -> a]
...

Even in this situation, C-cC-t on 'id' displays 'a -> a' in the minibuffer. GHC's -fdefer-type-errors enables this magic.

Also, you can make use of GHC's hole. Inserting "_" before "bar" and typing C-xC-s results in highlighting the second line again:

foo :: [a -> a] -> a -> a
foo xs = foldr _bar id xs
  where
    bar = (:)

C-c? displays:

Found hole `_bar' with type: (a -> a) -> (a -> a) -> a -> a
Where: `a' is a rigid type variable bound by
           the type signature for foo :: [a -> a] -> a -> a
           at /Users/kazu/c.hs:3:8
Relevant bindings include
  bar :: forall a. a -> [a] -> [a] (bound at /Users/kazu/c.hs:6:5)
  xs :: [a -> a] (bound at /Users/kazu/c.hs:4:5)
  foo :: [a -> a] -> a -> a (bound at /Users/kazu/c.hs:4:1)
...

More type holes

Suppose you have:

filterNothing :: [Maybe a] -> [a]

Typing M-t gets:

filterNothing :: [Maybe a] -> [a]
filterNothing = undefined

On the other hand, typing C-uM-t gets:

filterNothing :: [Maybe a] -> [a]
filterNothing xs = _body

Then, C-xC-s refreshes highlightings. When you type C-cC-f on "_body" and type "filter" in the minibuffer, you get:

filterNothing :: [Maybe a] -> [a]
filterNothing xs = filter _body_1 _body_2

Case handling

Suppose you have:

f :: [a] -> a
f x = _f_body

Typing M-t on "x" splits cases as follows:

f :: [a] -> a
f [] = _f_body
f (x:xs) = _f_body

Suppose you have:

f :: a -> Maybe a
f x = _f_body

Typing C-cC-a on "_f_body" and selecting one of possible cases in another window results in:

f :: a -> Maybe a
f x = Nothing