Edited at

vscode と haskell-ide-engine で Haskell 開発環境を構築する

本家のSSを引用

この画像は本家リポジトリのスクリーンショットを引用しています。

現在の最新バージョンは v0.12.0.0 です。この記事は以下のリビジョンで動作確認しています。

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ git rev-parse HEAD
3421a0e1deb34f65f979071989663ebc9f869199

また、vscode-hie-server の最新バージョンは 0.0.28 です。


haskell-ide-engine のビルド時間めちゃ長い問題について

現状、公式からビルド済みのバイナリは配布されていません。

Nix で Haskell IDE Engine をシュッと入れる」の方法でインストールすれば比較的短時間で終わるみたいです。興味ある方は試してみると良いかもしれません!


Haskell の開発環境について

みなさん Haskell の開発環境ってどうしてますか?僕は Vim and Haskell in 2016 を参考にしつつ、 haskell-vim-now で環境を整えていました。これはこれで便利なのですが、やっぱり IDE を使いたいって思う時ありますよね。

Haskell 界隈でもこの話題は昔から問題として認識されていて、Haskell で書かれている Leksah (10年以上続いているプロジェクト) や Haskell for Mac (有料ですが SpriteKit を使ってゲームを作れたりします。開発スピードは遅めです。Xcodeplayground 機能も実装されています。個人的に購入してみましたが stack と相性が悪いのですぐに使わなくなりました) などの IDE が存在します。

また、IDE を作るのではなく、バックエンドを実装するプロジェクトも存在します。

そして、ghc-modide-backend が力を合わせてすごいやつ作るぞ!となって、絶賛開発中なのがこちら。

将来的には、このプロジェクトに全て統合していくようです。

説明が長くなりましたが、Summer of Haskell 2017 に Haskell IDE Engine というプロジェクトがあり、以下を実装することを目標としていました。

今までは自分たちで hlintHaRe などのツールを別途インストールし、実行する必要がありましたが、hie を使うことでこれらの作業負担が無くなる点も Good Point だと思います。(Tools in the ecosystem を見てもらえればわかりますが、本当にたくさんあります。)

現在使える機能は以下の通りです。



  • hlint, ghc-mod を使った静的解析


  • apply-refact を使ったクイックフィックス

  • マウスホバー時の型情報の表示と hoogle を使ったドキュメントの表示

  • 定義へのジャンプ

  • トップレベル定義の一覧表示

  • ドキュメント内のハイライト参照

  • 自動補完


  • brittany, floskell を使ったコード整形


  • HaRe を使った名前変更リファクタリング

  • import 文の自動挿入

  • import 文からパッケージを cabalhpack に追加

  • typo の quick fix


  • hsimport を使った import 文の挿入


  • liquidhaskell のサポート

  • Case splitting

hiehlint, brittany, ghc-mod 等の各パッケージが提供している API を利用して実装しているため、それぞれのバイナリファイルは必要ありません。(つまり、stack install hlint などでインストールしなくても使えるということです)


hie のデメリット

良い部分だけ紹介するのは不公平なので、利用していて気になっている部分を箇条書きで列挙します。

一応、以下のように RTS フラグを設定してメモリの最大使用量を制限する方法が紹介されています。

#!/bin/sh

export HIE_SERVER_PATH=`which hie`

if [ "X" = "X$HIE_SERVER_PATH" ]; then
echo "Content-Length: 100\r\n\r"
echo '{"jsonrpc":"2.0","id":1,"error":{"code":-32099,"message":"Cannot find hie.exe in the path"}}'
exit 1
fi

hie +RTS -c -M4G -K4G -A16M -RTS --lsp $@

上記の問題はあるものの、その問題点を確実に上回るメリットがあるため現在も利用を続けています。


依存関係

git はすでにインストールされているものとします。


Debian/Ubuntu

λ sudo apt install libicu-dev libtinfo-dev libgmp-dev zlib1g-dev


zlib1g-dev公式ドキュメントに記載が無いため環境によっては不必要かもしれませんが、ハマりポイントっぽいのでインストールしておいた方が良いと思います。


Stack のインストール


stackのインストール

λ curl -sSL https://get.haskellstack.org/ | sh


既に stack をインストールしている人でバージョンが 2.1.3 より小さい場合は、以下のコマンドで更新しましょう。


stackの更新

λ stack upgrade

λ stack --version
Version 2.1.3, Git revision 0fa51b9925decd937e4a993ad90cb686f88fa282 (7739 commits) x86_64 hpack-0.31.2



パスを通す

すでに設定している方は必要ありません。

だいたいこんな感じです。必要に応じて変更しましょう。


パスを通す設定(mac)

λ echo 'export PATH=$(stack path --local-bin):$PATH' >> ~/.bash_profile

λ source ~/.bash_profile


パスを通す設定(ubuntu)

λ echo 'export PATH=$(stack path --local-bin):$PATH' >> ~/.bashrc

λ source ~/.bashrc


hie が対応している GHC のバージョン

install.hs スクリプトの help コマンドで、利用可能なコマンドの一覧が表示されます。利用可能な GHC のバージョン一覧もここで確認します。


利用可能なコマンド一覧

λ stack ./install.hs help

... 初回のみ GHC のインストールが始まる場合があります ...

λ stack ./install.hs help

Usage:
stack install.hs <target>
or
cabal new-run install.hs --project-file shake.project <target>

Targets:
help Show help message including all targets

build Builds hie with all installed GHCs
build-all Builds hie for all installed GHC versions and the data files
build-data Get the required data-files for `hie` (Hoogle DB)
hie-8.2.2 Builds hie for GHC version 8.2.2
hie-8.4.2 Builds hie for GHC version 8.4.2
hie-8.4.3 Builds hie for GHC version 8.4.3
hie-8.4.4 Builds hie for GHC version 8.4.4
hie-8.6.1 Builds hie for GHC version 8.6.1
hie-8.6.2 Builds hie for GHC version 8.6.2
hie-8.6.3 Builds hie for GHC version 8.6.3
hie-8.6.4 Builds hie for GHC version 8.6.4
hie-8.6.5 Builds hie for GHC version 8.6.5

stack-build Builds hie with all installed GHCs; with stack
stack-build-all Builds hie for all installed GHC versions and the data files; with stack
stack-build-data Get the required data-files for `hie` (Hoogle DB); with stack
stack-hie-8.2.2 Builds hie for GHC version 8.2.2; with stack
stack-hie-8.4.2 Builds hie for GHC version 8.4.2; with stack
stack-hie-8.4.3 Builds hie for GHC version 8.4.3; with stack
stack-hie-8.4.4 Builds hie for GHC version 8.4.4; with stack
stack-hie-8.6.1 Builds hie for GHC version 8.6.1; with stack
stack-hie-8.6.2 Builds hie for GHC version 8.6.2; with stack
stack-hie-8.6.3 Builds hie for GHC version 8.6.3; with stack
stack-hie-8.6.4 Builds hie for GHC version 8.6.4; with stack
stack-hie-8.6.5 Builds hie for GHC version 8.6.5; with stack

cabal-ghcs Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`.
cabal-build Builds hie with all installed GHCs; with cabal
cabal-build-all Builds hie for all installed GHC versions and the data files; with cabal
cabal-build-data Get the required data-files for `hie` (Hoogle DB); with cabal
cabal-hie-8.6.5 Builds hie for GHC version 8.6.5; with cabal
cabal-hie-8.6.1 Builds hie for GHC version 8.6.1; with cabal
cabal-hie-8.4.4 Builds hie for GHC version 8.4.4; with cabal

icu-macos-fix Fixes icu related problems in MacOS


もし GHC 8.0.2 のプロジェクトで hie を利用したい場合は hie-0.1.0.0 ブランチを利用する必要があります。


hie のインストール

hie はビルドに利用した GHC のバージョンのプロジェクトでしか動きません。(具体例: GHC-8.4.4 でビルドした hie は GHC-8.6.5 を利用するプロジェクトでは使えません)

そのため、各 GHC のバージョンに対応した hiehie-8.4.4 のようにリネームしてこの問題を回避しています。

通常の良くある stack install コマンドではなく install.hs スクリプトを使ったインストール方法を推奨するのは、それらのつまらない作業を全部やってくれるからです。また、このスクリプトは Shake というビルドシステムを利用しているため、OS に依存することなく実行可能です。なので Windows でも Linux でも install.hs を使ってインストールを行います。

インストール方法には build-all という全ての GHC のバージョンに対して hie をそれぞれインストールするコマンドもありますが、このコマンドはビルドに非常に時間がかかり、またディスクの消費も激しいです。そのため、プロジェクトで利用している GHC に対応したバージョンのみを個別にインストールする方法がおすすめです。

2つ以上のバージョンを利用したい場合は、次に説明するインストール方法を単純に組み合わせるだけで大丈夫です。


hie をバージョンごとにインストールする方法

以下は全て stack を使ってインストールする方法になります。cabal を使いたい人は後述の方法を試してください。


GHC 8.6.5

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ stack ./install.hs hie-8.6.5
λ stack ./install.hs build-data


GHC 8.6.4

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ stack ./install.hs hie-8.6.4
λ stack ./install.hs build-data


GHC 8.6.3

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ stack ./install.hs hie-8.6.3
λ stack ./install.hs build-data


GHC 8.6.2

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ stack ./install.hs hie-8.6.2
λ stack ./install.hs build-data


GHC 8.6.1

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ stack ./install.hs hie-8.6.1
λ stack ./install.hs build-data


GHC 8.4.4

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ stack ./install.hs hie-8.4.4
λ stack ./install.hs build-data


GHC 8.4.3

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ stack ./install.hs hie-8.4.3
λ stack ./install.hs build-data


GHC 8.4.2

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ stack ./install.hs hie-8.4.2
λ stack ./install.hs build-data


GHC 8.2.2

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ stack ./install.hs hie-8.2.2
λ stack ./install.hs build-data


GHC 8.0.2

λ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules

λ cd haskell-ide-engine
λ git checkout hie-0.1.0.0
λ git submodule update --init
λ stack --stack-yaml=stack-8.0.2.yaml install


stack ではなく cabal を使う

hie のビルドに stack build ではなく cabal new-build を使うこともできます。(ただし、現状は windows では動かないそうです)

現在インストールされている GHC のバージョンを確認するためには以下のコマンドを実行します。


インストールされているghcのバージョン確認例

$ stack install.hs cabal-ghcs

******************************************************************
Found the following GHC paths:
ghc-8.6.5: /Users/gupi/.ghcup/bin/ghc-8.6.5
ghc-8.6.1: /Users/gupi/.ghcup/bin/ghc-8.6.1
ghc-8.4.4: /Users/gupi/.ghcup/bin/ghc-8.4.4

******************************************************************


ビルド方法は stack の場合とほぼ同じですが、コマンドのプレフィックスに cabal がつきます。

# cabal-ghcs でリストアップされたコンパイラの全バージョンに対してビルドを行う (hie + hoogle)

λ stack ./install.hs cabal-build-all

## hie のビルドのみ
λ stack ./install.hs cabal-build

## hoogle ドキュメントのビルドのみ
λ stack ./install.hs cabal-build-data

# GHC のバージョンを指定してビルドする方法
λ stack ./install.hs cabal-hie-8.6.5


VSCODE の設定

無事にインストールが完了し、パスが通っている状態であればこのように hie のバージョンが表示されます。

λ hie --version

Version 0.12.0.0, Git revision 3421a0e1deb34f65f979071989663ebc9f869199 (dirty) (2973 commits) x86_64 ghc-8.4.4

設定可能な項目一覧

{

"languageServerHaskell": {
"hlintOn": Boolean,
"maxNumberOfProblems": Number
"diagnosticsDebounceDuration" : Number
"liquidOn" : Bool (default False)
"completionSnippetsOn" : Bool (default True)
"formatOnImportOn" : Bool (default True)
"formattingProvider" : String (default "brittany",
alternate "floskell")
}
}


hlint

hlint の最大ヒント数と有効/無効を設定することができます。


settings.json

{

"languageServerHaskell": {
"hlintOn": Boolean,
"maxNumberOfProblems": Number
}
}


liquidhaskell

liquidhaskell のエラーを表示してくれます。

"languageServerHaskell.liquidOn": true,


カスタムhieラッパー

デフォルトの hie-wrapper で満足できない場合は自分でカスタマイズできます。



"languageServerHaskell.useCustomHieWrapper": true,
"languageServerHaskell.useCustomHieWrapperPath": "hie-wrapper",


トラブルシューティング

本家の Troubleshooting も参考になる場合があります。


hie が見つからない

スクリーンショット 2018-10-15 19.04.27.png


hie executable missing, please make sure it is installed, see github.com/haskell/haskell-ide-engine.


画像のようなエラーメッセージが出た時は hie が見つからないということなので、以下のように実行ファイルのパスを languageServerHaskell.hieExecutablePath に指定します。

"languageServerHaskell.hieExecutablePath": "~/.local/bin/hie",

どこにインストールしたかわからない人は次のコマンドでパスを確認しましょう。


hieのパスを確認するコマンド

λ which hie

/home/guchi/.local/bin/hie


"print-build-platform" (exit 1): failed というエラーが出る

エラーメッセージは以下のような内容が表示されます。

readCreateProcess: <path>/bin/cabal-helper-wrapper "print-build-platform" (exit 1): failed

このエラーは cabal-helper-wrapper "print-build-platform" (exit 1): failed. #128 の可能性があります。

下記の内容を .bash_profile 等に追記すると解決します。また、この記事のコメント欄も参考にしてみてください。

export PATH=$(stack path --compiler-bin):$PATH


Error: spawn EACCES というエラーが出て hie が起動しない

[Error - 19:07:38] Starting client failed

Error: spawn EACCES
at _errnoException (util.js:1024:11)
at ChildProcess.spawn (internal/child_process.js:323:11)
at Object.exports.spawn (child_process.js:514:9)
at _getServerWorkingDir.then.serverWorkingDir (/home/guchi/.vscode/extensions/alanz.vscode-hie-server-0.0.24/node_modules/vscode-languageclient/lib/main.js:347:40)
at <anonymous>

上記のエラーは、パスの指定が間違っている場合などで出現するようです。

例えば、以下のパスはどちらも間違っています。自分の設定ファイルを確認してみましょう。


間違った指定その1

"languageServerHaskell.hieExecutablePath": "~/.local/bin/",



間違った指定その2

"languageServerHaskell.hieExecutablePath": "${HOME}/.local/bin/hie",


このように、正しいパスを指定しましょう。


正しい指定方法

"languageServerHaskell.hieExecutablePath": "~/.local/bin/hie",



happy のエラー

環境によっては happy が見つからないためエラーとなる場合があります。たぶんパスの問題ですが、とりあえず happy をインストールすれば良いです。

λ stack install happy

λ make build-all
# 中断した続きからビルドが開始される


text-icu パッケージのビルドエラー

macOS 環境だと、以下のようなエラーが出る場合があります。

--  While building custom Setup.hs for package text-icu-0.7.0.1 using:

/Users/bm12/.stack/setup-exe-cache/x86_64-osx/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-osx/Cabal-1.24.2.0 configure --with-ghc=/Users/bm12/.stack/programs/x86_64-osx/ghc-8.0.2/bin/ghc --with-ghc-pkg=/Users/bm12/.stack/programs/x86_64-osx/ghc-8.0.2/bin/ghc-pkg --user --package-db=clear --package-db=global --package-db=/Users/bm12/.stack/snapshots/x86_64-osx/lts-9.21/8.0.2/pkgdb --libdir=/Users/bm12/.stack/snapshots/x86_64-osx/lts-9.21/8.0.2/lib --bindir=/Users/bm12/.stack/snapshots/x86_64-osx/lts-9.21/8.0.2/bin --datadir=/Users/bm12/.stack/snapshots/x86_64-osx/lts-9.21/8.0.2/share --libexecdir=/Users/bm12/.stack/snapshots/x86_64-osx/lts-9.21/8.0.2/libexec --sysconfdir=/Users/bm12/.stack/snapshots/x86_64-osx/lts-9.21/8.0.2/etc --docdir=/Users/bm12/.stack/snapshots/x86_64-osx/lts-9.21/8.0.2/doc/text-icu-0.7.0.1 --htmldir=/Users/bm12/.stack/snapshots/x86_64-osx/lts-9.21/8.0.2/doc/text-icu-0.7.0.1 --haddockdir=/Users/bm12/.stack/snapshots/x86_64-osx/lts-9.21/8.0.2/doc/text-icu-0.7.0.1 --dependency=base=base-4.9.1.0 --dependency=bytestring=bytestring-0.10.8.1 --dependency=deepseq=deepseq-1.4.2.0 --dependency=text=text-1.2.2.2-9UQZjEJZQFSGMffj1Z5g00
Process exited with code: ExitFailure 1
Logs have been written to: /usr/local/share/haskell-ide-engine/.stack-work/logs/text-icu-0.7.0.1.log

Configuring text-icu-0.7.0.1...
Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2: Missing dependencies on foreign
libraries:
* Missing C libraries: icuuc, icui18n, icudata
This problem can usually be solved by installing the system packages that
provide these libraries (you may need the "-dev" versions). If the libraries
are already installed but in a non-standard location then you can use the
flags --extra-include-dirs= and --extra-lib-dirs= to specify where they are.
make: *** [build] Error 1

依存しいてるライブラリのパスがわからなくてパッケージのインストールに失敗しているため、以下のコマンドでパッケージをビルドしましょう。

λ stack ./install.hs icu-macos-fix


ディレクトリの削除

hie のディレクトリを削除すると上手く動かなくなりました。

hie: Could not find $libexecdir/cabal-helper-wrapper


If you are a cabal-helper developer you can set the environment variable
`cabal_helper_libexecdir' to override $libexecdir[1]. The following will
work in the cabal-helper source tree:

$ export cabal_helper_libexecdir=$PWD/dist/build/cabal-helper-wrapper

バイナリは ~/.local/bin にインストールされるため大丈夫かと思ったんですけど、ダメでした。

たぶんこの問題かな。ghc-modでcabal-helper-wrapperが見つからない問題の対応


VS Code のインストール


Ubuntu 18.04 LTS

公式ドキュメントで紹介されている、手動でのインストール方法でインストールすることにします。

λ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg

λ sudo install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/
λ sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'

λ sudo apt install apt-transport-https
λ sudo apt update
λ sudo apt install code # or code-insiders

このようなエラーが出る場合はライブラリが足りないので、追加でインストールします。

λ code

/usr/share/code/bin/../code: error while loading shared libraries: libXss.so.1: cannot open shared object file: No such file or directory

λ sudo apt install libxss1

code と入力すればすぐに vscode が起動します。

λ code

ss1.png


macOS Mojave (10.14.5)

公式サイトからバイナリが配布されているので、それをインストールするだけです。

ss2.png


拡張機能 (Haskell Language Server) の追加

VS Code marketplace から Haskell Language Server 拡張をインストールします。

1.png

インストール完了後、再読み込みすると有効化されます。

また、vscode 内からインストールすることも可能です。

1.png

Haskell Language Server をインストールすると Haskell Syntax Hilighting 拡張も同時にインストールされるため、何もしなくても色鮮やかなコードが表示されます。

1.png


機能について

ここが一番重要ですね!まだまだ開発途中なので出来ることは限られているのですが、それでも凄く便利です。ここから利用するスクリーションは本家リポジトリで紹介されている画像になります。


cabal, hpack へのパッケージ追加

add package

add package


typo quick fixes

typo quick fixes


不足している import の追加 (via hsimport)

Add missing imports


import 宣言の自動挿入 (0.0.18 以上)

import

このコマンドは package.yaml の依存関係から、選択した関数が含まれるモジュールをリストアップしてくれるので、その中から適切な物を選ぶと、自動的に挿入されます。

めちゃめちゃ便利です。


Lint

PROBLEMS (問題) のエリアには hlint, ghc-mod のエラーや警告が表示されます。クリックすると、該当する行までジャンプするので便利です。

lint


コードアクションとクイックフィックス

hlint に指摘されると行の左側に電球のマークが表示されます。これをクリックして適用するだけで、hlintの指摘通りにコードが書き換わります。

quickfix


マウスホバー時の型情報とドキュメント表示

マウスホバー時に型の情報とドキュメントが表示されます。ドキュメントの表示は hoogle を利用しています。

hoogle


ドキュメントが表示されない場合

以下の画像のように、画面上部に No hoogle db found. Check the README for instructions to generate one と表示されている場合はデータベースと上手く連携できていない状態です。

error.png

僕の環境では以下のバージョンでエラーとなってしまったので、 最新のLTSで hoogle をインストールし直しました。

λ hoogle --version

Hoogle 5.0.9, http://hoogle.haskell.org/

λ stack install hoogle --resolver lts
...

λ hoogle --version
Hoogle 5.0.17.6, http://hoogle.haskell.org/


プロジェクト固有のデータベースを利用する

stack のプロジェクトルートで通常通り hoogle のデータベースを生成すればOKです。

λ stack haddock --keep-going

cabal プロジェクトの場合は ~/.cabal/config に以下の設定を追記します。

documentation: True


定義へのジャンプ

jump


全てのトップレベル定義の一覧表示

Ctrl + P でコマンドパレットを開き @ を入力することでトップレベルに定義された関数の一覧を確認できます。クリックすると、その関数の定義にジャンプします。

list


ソースコード内のハイライト参照

マウスでドラッグするだけで、全てハイライトされます。

hilight


自動補完

文字を入力すると自動的に補完機能が働きます。タブキーで補完完了です。

complement


コード整形

以下のフォーマッターが利用できます。

formatting


名前の変更

HaRe を使って名前変更のリファクタリングができます。

hare


その他の拡張機能について

Haskell に関する拡張機能はそれほど多くはありませんが、Haskell GHCi debug viewer Phoityne などは GHCi debugger が使えるようになるという面白い拡張です。

一応こんな感じで動きます。

phoityne-vscode.gif


hie がサポートしているエディタ

hie は vscode に限らず Language Server Protocol が利用できれば、どんなエディタでも利用できます。公式のREADMEで明記があるのは以下のエディタです。


まとめ

vscode 内の統合ターミナルウィンドウで以下のコマンドを一度入力しておけば、保存時に自動的にリビルドしてくれるのでオススメです。

λ stack test --fast --file-watch --no-run-tests

Haskell入門 関数型プログラミング言語の基礎と実践 という Haskell の基礎から実践的なアプリケーション開発までを網羅している新しい Haskell 入門書が発売されました。これを機に Haskelll やってみようかな!と思っている方は、この環境で試してみても良いのではないかと思います。

現在、Haskell のアプリケーション開発について書いてある本は Real World Haskell しかありませんし、あの本は出る時期が早すぎた感が否めない (けど、本当に素晴らしい内容の本です) ですし、しかも超絶分厚い (650ページぐらいあります) ので本気でやる人以外は厳しいですよね・・・。

それと比べれば、敷居がとても低そうなので Haskell で開発したい人にオススメです!

最新の IDE 環境でモダンな Haskell アプリケーション開発を学びましょう!


参考