27 KiB
Haskell layer
- Description
- Install
- Key bindings
- Syntax checking
- FAQ
- The REPL doesn't work
- The REPL is stuck
- I am using
stack
andghc-mod
, butghc-mod
doesn't work ghc-mod
doesn't work- Indentation doesn't reset when pressing return after an empty line
- Flycheck displays HLint warnings but not errors
- I can see highlighted errors but they don't appear in the error list
- Flycheck doesn't work
- Flycheck doesn't work with
stack
- haskell-mode commands don't work
ghc-mod
andhaskell-mode
commands overlap. How do I know which command belongs to what?- Some commands start with
ghc-
and some withhaskell-
. What does that mean? - Why doesn't the HLint Flycheck checker work when the Intero backend is enabled?
Description
This layer adds support for the Haskell language.
Features:
- syntax highlighting for haskell source, cabal files, C– source,
- auto-completion with one of the selected backends (
intero
,dante
,ghci
orghc-mod
).
This layer is under construction, it needs your contributions and bug reports.
Install
Layer
To use this configuration layer, add it to your ~/.spacemacs
. You will need to
add haskell
to the existing dotspacemacs-configuration-layers
list in this
file.
Dependencies
This layer requires some cabal packages:
apply-refact
(required byhlint-refactor
)hlint
(required byhlint-refactor
)stylish-haskell
(optional forhaskell-mode
)hasktags
(optional)hoogle
(optional forhaskell-mode
andhelm-hoogle
)ghc-mod
(optional for completion)intero
(optional for completion)
To install them, use the following command (or the stack
equivalent):
$ cabal install apply-refact hlint stylish-haskell hasktags hoogle
Setup PATH
First of all, make sure that your $PATH
contains the installation path for
Haskell tools like ghc
, ghci
etc. It depends on how you have installed
ghc
, but you can always check it by running which ghc
in your terminal.
Stack
users should only add the installation path of stack
itself. Usually
it's ~/.local/bin
.
Then make sure that your $PATH
contains the installation path for the cabal
packages. If you are using cabal
it should be ~/.cabal/bin
or
~/Library/Haskell/bin
(for 'Haskell for Mac' users). If you are using stack
then it should be ~/.local/bin
.
For information about setting up $PATH
, check out the corresponding section in
the FAQ (SPC h SPC $PATH RET
).
Choosing a backend
To choose a default backend set the layer variable haskell-completion-backend
:
(haskell :variables haskell-completion-backend 'ghci)
Note that in order to enable completion, you'll have to enable the
auto-completion
layer as well.
Alternatively the lsp
backend will be automatically chosen if the layer lsp
is used and you did not specify any value for haskell-completion-backend
.
Backend can be chosen on a per project basis using directory local variables
(files named .dir-locals.el
at the root of a project), an example to use the
lsp
backend:
;;; Directory Local Variables
;;; For more information see (info "(emacs) Directory Variables")
((haskell-mode (haskell-completion-backend . lsp)))
Note: you can easily add a directory local variable with SPC f v d
.
Supported values for haskell-completion-backend
arer intero
, dante
,
ghci
, ghc-mod
, and lsp
. ghci
(company-ghci
) is used by default unless
the layer lsp
is used. ghci
is the default backend because it doesn't
require any dependencies, and it works with both stack
and pure cabal
projects.
(setq-default dotspacemacs-configuration-layers
'(auto-completion
(haskell :variables haskell-completion-backend 'intero)))
company-ghci
company-ghci communicates directly with ghci
, in order to provide completion.
To use it, you have to call haskell-process-load-or-reload
(SPC s b
).
intero
Intero
only works for stack
users. You can install the intero
executable
manually, by calling stack install intero
, but this step is optional as
Intero
installs itself.
dante
dante
works for cabal
, nix
, sytx
, and stack
users.
dante
requires Emacs 25.
ghc-mod
ghc-mod enhances haskell-mode
, with for example code completion, templates,
case-splitting and much more. In order to use it, you need to install the
executable with cabal install ghc-mod
(or the stack
equivalent).
Stack
users also should make sure that dist/setup-config
doesn't exist in
the project root. As it will confuse ghc-mod
. For more troubleshooting,
checkout this document.
Also note that ghc-mod
only works with the GHC
version that was used to
build ghc-mod
. You can check which version was used by calling
ghc-mod --version
.
lsp
lsp
requires an appropriate installation of hie
the official Haskell language server to work properly.
hie
is like an improved version of ghc-mod
it is best installed by building it locally as it requires
that the same GHC version has been used to compile your code as has been used for hie
.
To install it please refer to the official installation instructions here.
Enabling the lsp
backend requires the lsp
layer to be enabled, and provides access to
all the additional lsp-mode
key bindings. As such it is more of a full backend than just
a completion backend.
Optional extras
The Haskell layer supports some extra features, which can be enabled through the layer variables.
structured-haskell-mode
Currently there is no support for structured-haskell-mode, since it doesn't play
very well with non-emacs editing styles (structured-haskell-mode/#81). Emacs
editing style users can easily enable it by adding structured-haskell-mode
to
the list of dotspacemacs-additional-packages
in your .spacemacs
file. For
more installation instructions, please refer to the official documentation at
the structured-haskell-mode page. In case you are a non-emacs editing style user
and still want to use structured-haskell-mode
- use it at your own risk.
Any contributions that will help to solve issues with structured-haskell-mode
are warmly welcome!
hindent
hindent is an extensible Haskell pretty printer, which lets you reformat your
code. You need to install the executable with cabal install hindent
or
stack install hindent
.
To enable it you have to toggle the variable haskell-enable-hindent
.
See examples here.
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-hindent t)))
Key bindings
All Haskell specific bindings are prefixed with the major-mode leader SPC m
.
Top-level commands are prefixed by SPC m
:
Key binding | Description |
---|---|
SPC m g g |
go to definition or tag |
SPC m g i |
cycle the Haskell import lines or return to point (with prefix arg) |
SPC m F |
format buffer using haskell-stylish |
SPC m f |
format declaration using hindent (if enabled) |
Documentation
Documentation commands are prefixed by SPC m h
Key binding | Description |
---|---|
SPC m h d |
find or generate Haddock documentation for the identifier under the cursor |
SPC m h f |
do a helm-hoogle lookup |
SPC m h h |
do a Hoogle lookup |
SPC m h H |
do a local Hoogle lookup |
SPC m h i |
gets information for the identifier under the cursor |
SPC m h t |
gets the type of the identifier under the cursor |
SPC m h y |
do a Hayoo lookup |
Debug
Debug commands are prefixed by SPC m d
:
Key binding | Description |
---|---|
SPC m d a |
abandon current process |
SPC m d b |
insert breakpoint at function |
SPC m d B |
delete breakpoint |
SPC m d c |
continue current process |
SPC m d d |
start debug process, needs to be run first |
SPC m d n |
next breakpoint |
SPC m d N |
previous breakpoint |
SPC m d p |
previous breakpoint |
SPC m d r |
refresh process buffer |
SPC m d s |
step into the next function |
SPC m d t |
trace the expression |
Debug Buffer
Key binding | Description |
---|---|
RET |
select object at the point |
a |
abandon current computation |
b |
break on function |
c |
continue the current computation |
d |
delete object at the point |
i |
step into the next function |
r |
refresh the debugger buffer |
s |
go to next step to inspect bindings |
S |
go to previous step to inspect the bindings |
t |
trace the expression |
REPL
REPL commands are prefixed by SPC m s
:
Key binding | Description |
---|---|
SPC m s b |
load or reload the current buffer into the REPL |
SPC m s c |
clear the REPL |
SPC m s s |
show and switch to the REPL |
SPC m s S |
show the REPL without switching to it |
C-j |
switch to next history item |
C-k |
switch to previous history item |
C-l |
clear the REPL |
Intero REPL
Intero REPL commands are prefixed by SPC m i
:
Key binding | Description |
---|---|
SPC m i c |
change directory in the backend process |
SPC m i d |
reload the module DevelMain and then run DevelMain.update |
SPC m i k |
stop the current worker process and kill its associated |
SPC m i l |
list hidden process buffers created by intero |
SPC m i r |
restart the process with the same configuration as before |
SPC m i t |
set the targets to use for stack ghci |
Cabal commands
Cabal commands are prefixed by SPC m c
:
Key binding | Description |
---|---|
SPC m c a |
cabal actions |
SPC m c b |
build the current cabal project, i.e. invoke cabal build |
SPC m c c |
compile the current project, i.e. invoke ghc |
SPC m c v |
visit the cabal file |
Cabal files
These commands are available in a cabal file.
Key binding | Description |
---|---|
SPC m d |
add a dependency to the project |
SPC m b |
go to benchmark section |
SPC m e |
go to executable section |
SPC m t |
go to test-suite section |
SPC m m |
go to exposed modules |
SPC m l |
go to library section |
SPC m n |
go to next subsection |
SPC m p |
go to previous subsection |
SPC m s c |
clear the REPL |
SPC m s s |
show the REPL without switching to it |
SPC m s S |
show and switch to the REPL |
SPC m N |
go to next section |
SPC m P |
go to previous section |
SPC m f |
find or create source-file under the cursor |
Refactor
Refactor commands are prefixed by SPC m r
:
Key binding | Description |
---|---|
SPC m r b |
apply all HLint suggestions in the current buffer |
SPC m r i |
reformat imports from anywhere in the buffer |
SPC m r r |
apply the HLint suggestion under the cursor |
SPC m r s |
list all Intero suggestions |
Only some of the HLint suggestions can be applied.
To apply the Intero suggestions, press `C-c C-c` when the window is open.
Both the HLint and Intero suggestions appear in the same window.
Ghc-mod
These commands are only available when ghc-mod is enabled.
For more info, see http://www.mew.org/~kazu/proj/ghc-mod/en/emacs.html
ghc-mod commands are prefixed by SPC m m
:
Key binding | Description |
---|---|
SPC t |
insert template |
SPC m m u |
insert template with holes |
SPC m m a |
select one of possible cases (ghc-auto ) |
SPC m m f |
replace a hole (ghc-refine ) |
SPC m m e |
expand template haskell |
SPC m m n |
go to next type hole |
SPC m m p |
go to previous type hole |
SPC m m > |
make indent deeper |
SPC m m < |
make indent shallower |
Insert template
SPC m m t
inserts a template. What this means is that in the beginning of a
buffer, module Foo where
is inserted. On a function without signature, the
inferred type is inserted. On a symbol foo
without definition, foo =
undefined
is inserted or a proper module is imported. SPC m m u
inserts a
hole in this case. On a variable, the case is split. When checking with hlint,
the original code is replaced with hlint's suggestion if possible.
Intero
This command is only available when intero is enabled.
This top-level command is prefixed by SPC m
:
Key binding | Description |
---|---|
SPC m g b |
return from definition |
Syntax checking
At the moment there are four components, which can check the syntax and indicate errors and warnings in the code. Those components are:
- flycheck
- hlint (via flycheck)
- ghc-mod
- haskell-mode interactive
Since all of these components can be active at the same time, it can be tricky to
know which component is displaying which message, especially when they disagree,
or if one isn't working. Only flycheck errors (ghc and hlint) are displayed in
the error list and can be navigated between, using the standard Spacemacs key
bindings (under SPC e
) even though errors from other modes might highlight the
actual buffer.
Flycheck
This is the standard Spacemacs way of syntax checking, and it's also the most elaborate. You need to install the syntax-checking layer first. Please read the layer's documentation on how to interact with flycheck.
Flycheck has different Haskell checkers: haskell-ghc
, haskell-stack-ghc
and
haskell-hlint
. Normally it can detect the best one to use automatically, but
if it doesn't work, then you can change it with SPC e s
.
HLint
HLint is a linter for Haskell. It doesn't detect errors (as long as it can parse the file) but bad coding style and code smell. The HLint checker is called after the flycheck GHC checker.
ghc-mod
Ghc-mod, when enabled, also does syntax checking. It doesn't highlight errors,
but instead displays an exclamation point in the fringe. You can navigate
between errors using ghc-goto-next-error
(M-n
) and ghc-goto-prev-error
(M-p
).
Interactive haskell-mode
Finally, interactive haskell-mode (SPC m s b
) also displays errors. These
errors can be navigated to, from the interactive buffer (by clicking on the
error) or using haskell-goto-next-error
(M-n
) and haskell-goto-prev-error
(M-p
).
Flymake
An alternative to syntax checking is to build your projects with
flymake-compile
. It doesn't highlight errors in the buffer, but it's more
reliable. The error navigation is similar to interactive haskell-mode.
Troubleshooting
Flycheck and ghc-mod can fail silently for miscellaneous reasons. See the FAQ for troubleshooting.
FAQ
The REPL doesn't work
Usually haskell-mode
is great at figuring out which interactive process to
bring up. But if you are experiencing problems with it, then you can help
haskell-mode
by setting haskell-process-type
as in following code:
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-process-type 'stack-ghci)))
Available options are:
- ghci
- cabal-repl
- cabal-new-repl
- cabal-dev
- cabal-ghci
- stack-ghci
The REPL is stuck
Make sure that there's a space between the REPL's λ>
prompt and the cursor.
When there is no space, then the REPL will behave as if it's stuck. Usually,
when you enter normal state, the cursor moves backwards by one character, so there
is no required space when you switch to insert mode. There is a possible
workaround - just add the following snippet to your dotspacemacs/user-config
function:
(when (configuration-layer/layer-used-p 'haskell)
(add-hook 'haskell-interactive-mode-hook
(lambda ()
(setq-local evil-move-cursor-back nil))))
It makes the cursor stay in the right place in the REPL buffer when you enter normal state. Which in most cases helps you to avoid the problem with 'stuck' REPL.
Also, some users might want to start the REPL in insert mode. This is done by
placing the following snippet in your dotspacemacs/user-config
function:
(when (configuration-layer/layer-used-p 'haskell)
(defadvice haskell-interactive-switch (after spacemacs/haskell-interactive-switch-advice activate)
(when (eq dotspacemacs-editing-style 'vim)
(call-interactively 'evil-insert))))
I am using stack
and ghc-mod
, but ghc-mod
doesn't work
Make sure that a dist
directory doesn't exist in your project root. If it
exists, just remove it and try again.
ghc-mod
doesn't work
First of all - make sure that the version of ghc
matches the version of ghc
that was used to build ghc-mod
. To get the latter, call ghc-mod --version
in
the terminal. If they don't match then you'll have to rebuild ghc-mod
.
Stack
provides the ability to use different ghc
versions across different
projects. If you're using this feature, then you'll have to rebuild ghc-mod
quite often. If you only use ghc-mod
for completion, and don't want to rebuild
ghc-mod
every time you switch projects, then you'd better disable ghc-mod
support, so that company-ghci
will be used for completion.
The second thing to do if it's still not working - is to call ghc-mod debug
in
the root of the project that you're currently working on. Make sure that it
doesn't show any errors. If there are errors that you can't solve - then it's
better to report them upstream.
Indentation doesn't reset when pressing return after an empty line
This is the intended behavior in haskell-indentation-mode
. If you want to
reset the indentation when pressing return after an empty line, add the
following snippet into your dotspacemacs/user-config
function.
(defun haskell-indentation-advice ()
(when (and (< 1 (line-number-at-pos))
(save-excursion
(forward-line -1)
(string= "" (s-trim (buffer-substring (line-beginning-position) (line-end-position))))))
(delete-region (line-beginning-position) (point))))
(advice-add 'haskell-indentation-newline-and-indent
:after 'haskell-indentation-advice)
Flycheck displays HLint warnings but not errors
The HLint checker is called after the normal flycheck checker, even if the checker fails. Check the Flycheck doesn't work section.
I can see highlighted errors but they don't appear in the error list
The error list is only set by flycheck. You are probably seeing errors highlighted by either ghc-mode or haskell-mode. Check the Flycheck doesn't work section.
Flycheck doesn't work
You can use the flycheck-compile
command to check what's wrong with flycheck.
This will show you the exact command line that's used, and its output.
If you are using stack
, check the Flycheck doesn't work with stack
section.
Flycheck doesn't work with stack
First check that flycheck uses the correct checker, and all the paths are
properly configured using flycheck-verify-setup
(SPC e v
). You can force the
checker with flycheck-select-checker
(SPC e s
) to ensure that it uses
haskell-stack-ghc
. If it still doesn't work, then it could be one of the
following problems:
- The
stack
build directory is wrong - The project root is not set properly
The stack
build directory is wrong
The path to the build directory, which contains some generated files, is
normally under .stack-work/install/<os>/Cabal-<version>/build
.
However the version of the cabal library that's used by stack
to generate the
directory name is not the version of the cabal library that's installed by
stack
but rather the version of cabal that's associated to the GHC version.
This error can happen after upgrading cabal or cabal-install. To check if this
is the problem, compare the path name of the build path that's used by flycheck
using flycheck-compile
and compare it to the actual path in the .stack-work
directory. If they are different, then you'll need to reinstall ghc using the
command stack setup --upgrade-cabal
.
The Project root directory is not set properly
Flycheck launches the GHC command, not from the project root directory, but from the directory of the file that's being checked. This is normally not a problem, as all the paths are set properly, however it could be a problem if some template Haskell functions use relative paths (e.g. in Yesod scaffolded projects).
Until it's fixed in flycheck, the workaround is to wrap the stack
command in
order to run all subcommands from the project's root directory. You can do so
with the following script:
#!/bin/bash
cd `stack path --project-root`
stack $*
Make sure you set flycheck-haskell-stack-ghc-executable
to this script.
haskell-mode commands don't work
Some (most) of the haskell-mode commands only work when haskell-mode is in
interactive mode, i.e. has an interactive session associated with it. Load it
using SPC m s b
.
ghc-mod
and haskell-mode
commands overlap. How do I know which command belongs to what?
ghc-mod commands are prefixed with ghc-
, haskell-mode ones are prefixed with
haskell-
.
Some commands start with ghc-
and some with haskell-
. What does that mean?
Commands starting with ghc-
are ghc-mod commands. Commands starting with
haskell-
are haskell-mode commands.
Why doesn't the HLint Flycheck checker work when the Intero backend is enabled?
By default, only the Intrero checker will be enabled if you manually set the Intero backend as described in Choosing a backend.
To also enable the HLint checker, use flycheck-add-next-checker
to set the
HLint checker after the Intero checker.
(defun dotspacemacs/user-init ()
(with-eval-after-load 'intero
(flycheck-add-next-checker 'intero '(warning . haskell-hlint))))