1f993bddf6
For ivy users: be sure to update your dotfile by replacing spacemacs-ivy by ivy |
||
---|---|---|
.. | ||
img | ||
config.el | ||
packages.el | ||
README.org |
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 - 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?
Description
This layer adds support for the Haskell language.
Features:
- syntax highlighting for haskell source, cabal files, C– source,
- auto-completion with company-ghc.
This layer is in 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:
hlint
stylish-haskell
hasktags
ghc-mod
hoogle
To install them, use following command (or the stack
equivalent):
$ cabal install stylish-haskell hlint hasktags ghc-mod 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 add only the installation path of stack
itself. Usually
it's ~/.local/bin
.
Then make sure that your $PATH
contains the installation path for 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
).
ghc-mod support
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 stack
equivalent). Note that
ghc-mod
support is enabled by default, so if you want to disable it, you must
do it explicitly in your .spacemacs
file.
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-ghc-mod-support nil)))
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.
Stack users
From time to time ghc-mod
is not available via latest Stackage LTS version. So
if you have problems with calling stack install ghc-mod
, try to use stack
install ghc-mod --resolver lts-3.1
(the last known LTS version that had
ghc-mod
). But even if it doesn't work, don't panic, it's easy to install it
from sources.
# clone cabal-helper
$ git clone https://github.com/DanielG/cabal-helper.git
# cd into cloned repository
$ cd cabal-helper
# init stack, so cabal-helper can be installed using stack
$ stack init
# now install it
$ stack install
# go back where you was
$ cd ..
# and remove cabal-helper repository since you don't need it
$ rm -rf cabal-helper
# now clone ghc-mod
$ git clone https://github.com/kazu-yamamoto/ghc-mod.git
# and cd into it
$ cd ghc-mod
# again, let's init stack
$ stack init
# now install it
$ stack install
# go back
$ cd ..
# and remove ghc-mod since you don't need it
$ rm -rf ghc-mod
Optional extras
The Haskell layer supports some extra features that can be enabled through layer variables.
GHCi-ng support
ghci-ng adds some nice features to haskell-mode
, and is supported in Spacemacs
by a layer variable:
Follow the instructions to install ghci-ng (remember to add :set +c
in
~/.ghci
), next set the layer variable:
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-ghci-ng-support t)))
Once ghci-ng is enabled, two of the old keybindings are overriden with improved versions from ghci-ng, and a new keybinding available:
Key Binding | Description |
---|---|
SPC m h t |
gets the type of the identifier under the cursor or for the active region |
SPC m g g |
go to definition |
SPC m u |
finds uses of identifier |
Stack users
Stack
and ghci-ng
doesn't play well with each other, so the general advice
is to avoid mixing them. But, if you want mix them anyway, you'll need to set
haskell-process-type
explicitly:
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-process-type 'ghci)))
;; or
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-process-type cabal-repl)))
This is needed, because by default haskell-process-type
is set to auto
and
if you have stack.yaml
file in the root of your project, stack-ghci
will be
used as process type.
ghc-mod users
If you want to use SPC m h t
from ghc-mod
instead of ghci-ng
, then you
need to add following line in your dotspacemacs/user-config
:
(spacemacs/set-leader-keys-for-major-mode 'haskell-mode
"mht" 'ghc-show-type)
This might be useful, because ghc-mod
doesn't require active REPL in order to
get type of symbol.
structured-haskell-mode
structured-haskell-mode, or shm, replaces default haskell-mode auto-indentation and adds some nice functionalities.
To install shm
run cabal install structured-haskell-mode
(or stack
equivalent).
To enable shm
set the layer variable:
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-shm-support t)))
After shm has been enabled, some of the evil normal state bindings are overridden:
Key Binding | Description |
---|---|
D |
shm/kill-line |
R |
shm/raise |
P |
shm/yank |
( |
shm/forward-node |
) |
shm/backward-node |
For a nice visualization of these functions, please refer to the github page for structured-haskell-mode.
Warning structured-haskell-mode doesn't play very well with evil
(structured-haskell-mode/#81). So it's recommended only to be used with the
emacs
editing style.
hindent
hindent is an extensible Haskell pretty printer, which let's you
reformat your code. You need to install the executable with cabal
install hindent
or stack install hindent
To enable it you have to set the variable haskell-enable-hindent-style
to a
supported style. The available styles are:
- fundamental
- johan-tibell
- chris-done
- gibiansky
See examples here.
(setq-default dotspacemacs-configuration-layers
'((haskell :variables haskell-enable-hindent-style "johan-tibell")))
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 d |
start debug process, needs to be run first |
SPC m d b |
insert breakpoint at function |
SPC m d n |
next breakpoint |
SPC m d N |
previous breakpoint |
SPC m d B |
delete breakpoint |
SPC m d c |
continue current process |
SPC m d a |
abandon current process |
SPC m d r |
refresh process buffer |
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 the REPL without switching to it |
SPC m s S |
show and switch to the REPL |
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
This 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 libary 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 |
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 m m 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,
original code is replaced with hlint's suggestion if possible.
Syntax checking
At the moment there are four components which can check the syntax and indicates somehow error and warnings in the code. Those components are
- flycheck
- hlint (via flycheck)
- ghc-mod
- haskell-mode interactive
As all 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
one is not working. Only flycheck errors (ghc and hlint) are displayed in the
error list and can be navigated 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 to do syntax checking and the most elaborate. You need the syntax-checking layer to enable this. Please the documentation for that layer on how to interact with flycheck.
Flycheck has different Haskell checkers: haskell-ghc
, haskell-stackghc
and
haskell-hlint
. Normally it can automatically detect the best one to use, but
if it doesn't work, you can change it using 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 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 project using
flymake-compile
. It doesn't highlight error in the buffer but is more
reliable. The error navigation is similar to interactive haskell-mode.
Troublesshooting
Flycheck and ghc-mod can fail silently for miscellaneous reasons. See the /TakeV/spacemacs/src/commit/818afdfc716c3b078af53272f0f893882334870a/layers/+lang/haskell/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 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-dev
- cabal-ghci
- stack-ghci
The REPL is stuck
Make sure that when you are typing anything in REPL there is a space between
what you type and λ>
. When there is no space - REPL will behave as it's stuck.
Usually, when you enter normal state, cursor is moved back, so there is no
required space when you switch to insert mode. There is possible workaround -
just add following snippet to your dotspacemacs/user-config
function:
(when (configuration-layer/layer-usedp 'haskell)
(add-hook 'haskell-interactive-mode-hook
(lambda ()
(setq-local evil-move-cursor-back nil))))
It will make cursor stay at 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 REPL in insert mode. For this to happen you
could place following snippet in your dotspacemacs/user-config
function:
(when (configuration-layer/layer-usedp '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 dist
directory doesn't exist in your project root. So if it
exists, just remove it and try again.
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 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 normal flycheck checker even if the checker fails. Check the /TakeV/spacemacs/src/commit/818afdfc716c3b078af53272f0f893882334870a/layers/+lang/haskell/Flycheck%20doesn't%20work 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 /TakeV/spacemacs/src/commit/818afdfc716c3b078af53272f0f893882334870a/layers/+lang/haskell/Flycheck%20doesn't%20work section.
Flycheck doesn't work
You can check what is wrong with flycheck with the flycheck-compile
command.
This will show you the exact command line used and its output.
If you are using stack, check the /TakeV/spacemacs/src/commit/818afdfc716c3b078af53272f0f893882334870a/layers/+lang/haskell/Flycheck%20doesn't%20work%20with%20=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 it uses
haskell-stack-ghc
. If it still doesn't work, 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 containing some generated files is normally
under .stack-work/install/<os>/Cabal-<version>/build
.
However, the version of the cabal library used by stack to generate the
directory name is not the version of the cabal library installed by stack, but
the version of cabal 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 used by flycheck using flycheck-compile
and
compare it to to the actual path in the .stack-work
directory. If they are
different you 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 the directory of the file 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 the wrap the stack command to run all subcommands from the project root directory. You can do so with the following script:
#!/bin/bash
cd `stack --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 works when haskell-mode is in
interactive mode, i.e. as a interactive session associated to 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.