#+TITLE:   lang/haskell
#+DATE:    January 16, 2017
#+SINCE:   v0.7
#+STARTUP: inlineimages

* Table of Contents :TOC:
- [[#description][Description]]
  - [[#external-resources][External resources]]
  - [[#module-flags][Module Flags]]
  - [[#plugins][Plugins]]
- [[#prerequisites][Prerequisites]]
  - [[#cabal][Cabal]]
  - [[#lsp-haskell-language-server][LSP (haskell-language-server)]]
  - [[#lsp-ghcide][LSP (ghcide)]]
  - [[#stack][Stack]]
  - [[#haskell-packages][Haskell packages]]
- [[#configuration][Configuration]]
  - [[#using-the-new-style-cabal-repl][Using the new-style cabal REPL]]
- [[#troubleshooting][Troubleshooting]]

* Description
This module adds [[https://www.haskell.org/][Haskell]] support, powered by either [[https://github.com/jyp/dante][dante]] (the default) or LSP
(haskell-language-server or ghcide).

+ Code completion (~company-ghc~)
+ Look up documentation (~hoogle~)
+ eldoc support (~dante~)
+ REPL (~ghci~)
+ Syntax-checking (~flycheck~)
+ Code navigation (~dante~)
+ [[https://github.com/hlissner/doom-snippets/tree/master/haskell-mode][Snippets]]

** External resources
Here are a few resources I've found indispensable in my Haskell adventures:

+ [[http://learnyouahaskell.com/][Learn you a haskell for great good]]
+ [[http://haskellbook.com/][Haskell Programming from first principles]]
+ [[https://github.com/krispo/awesome-haskell][Awesome Haskell]]: an extensive list of haskell resources
+ [[https://docs.haskellstack.org/en/stable/README/][The Haskell Tool Stack docs]]
 
** Module Flags
+ =+dante= Enables dante; a fork of intero aimed at lightweightedness. It
  doesn't depend on =stack=, supports both ~cabal~-only and ~stack~ projects,
  but lacks eldoc support.
+ =+ghcide= Enables LSP support with ghcide (requires the ~:tools lsp~ module).
+ =+lsp= Enables LSP support with haskell-language-server (requires the ~:tools lsp~
  module).

** Plugins
+ [[https://github.com/haskell/haskell-mode][haskell-mode]]
+ =+dante=
  + [[https://github.com/jyp/dante][dante]]
  + [[https://github.com/jyp/attrap][attrap]]
+ =+lsp=
  + [[https://github.com/emacs-lsp/lsp-haskell][lsp-haskell]]

* Prerequisites
Depending on whether you use Dante, haskell-language-server or ghcide, your
dependencies will differ:

+ Dante users need =cabal=, =ghc= and =ghc-mod=
+ LSP users need the =haskell-language-server= LSP server OR =ghcide=
+ All users will need the =hoogle= package

** Cabal
To use Dante, you need =cabal= (the haskell package builder) and =ghci= (the
compiler, syntax checker & repl):

*** MacOS
#+BEGIN_SRC sh
brew install cabal-install ghc
#+END_SRC

*** Arch Linux
#+BEGIN_SRC sh
sudo pacman -S cabal-install ghc
#+END_SRC

*** openSUSE
#+BEGIN_SRC sh :dir /sudo::
sudo zypper install cabal-install ghc
#+END_SRC

** LSP (haskell-language-server)
You will need =stack= and =git= installed.

You will find a comprehensive [[https://github.com/haskell/haskell-language-server#installation][instructions for haskell-language-server on its project page]], but if you are using [[https://www.haskell.org/ghcup/][ghcup]]:

#+BEGIN_SRC bash
ghcup install hls
#+END_SRC

** LSP (ghcide)
See https://github.com/digital-asset/ghcide for install instructions.

** Stack
To use LSP, you need =stack=:

*** MacOS
#+BEGIN_SRC sh
brew install haskell-stack
stack setup
#+END_SRC
*** Arch Linux
#+BEGIN_SRC sh
sudo pacman -S stack
# Replace pacaur with your AUR package manager of choice
pacaur -S ncurses5-compat-lib
stack setup
#+END_SRC

*** openSUSE
#+BEGIN_SRC sh :dir /sudo::
sudo zypper install stack
stack setup
#+END_SRC

** Haskell packages
You'll need to install the following packages using ~stack~ or ~cabal~:

+ (Dante users) =ghc-mod=
  #+BEGIN_SRC sh
  stack install ghc-mod
  # or
  cabal install ghc-mod
  #+END_SRC
+ =hoogle=
  #+BEGIN_SRC sh
  cabal update
  cabal install happy haskell-src-exts   # ghc-mod/hoogle dependencies
  cabal ghc-mod hoogle
  # or
  stack install ghc-mod
  stack install hoogle
  #+END_SRC

And ensure the binaries for these packages are in your ~PATH~, e.g.

#+BEGIN_SRC sh
# place this in your profile file, like ~/.bash_profile or ~/.zshenv
export PATH="~/.local/bin:$PATH"
#+END_SRC

* Configuration
** Using the new-style cabal REPL
=haskell-mode= will typically detect what REPL to run based on your project
(e.g. stack, (old-style) cabal or ghc). If you want the new-style cabal REPL you
must set ~haskell-process-type~ manually:

#+BEGIN_SRC emacs-lisp
(setq haskell-process-type 'cabal-new-repl)
#+END_SRC

* Troubleshooting
+ Stack users: a ~dist/setup-config~ file in your project may cause [[https://github.com/DanielG/ghc-mod/wiki#known-issues-related-to-stack][ghc-mod to
  not work]].
