Haskell
環境構築
入門
VSCode
haskell-ide-engine

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

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

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

$ git clone https://github.com/haskell/haskell-ide-engine --recurse-submodules
$ cd haskell-ide-engine
$ git rev-parse HEAD
ce022201ee54fc0cf509da7942e228dd0f1b65d9

Haskell の開発環境について

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

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

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

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

将来的には、このプロジェクトに全て統合していくようです。詳しい内容は This is not yet another ghc-mod or ide-backend project に書いてあるので、興味のある方は読んでみてください。

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

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

結果として全て完了したそうなので、実際に使ってみました。(個人的には Haskell-tools がどうなっていくのか少し気になります)

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

  • hlint, ghc-mod を使った静的解析
  • apply-refact を使ったクイックフィックス
  • マウスホバー時の型情報の表示と hoogle を使ったドキュメントの表示
  • 定義へのジャンプ
  • トップレベル定義の一覧表示
  • ドキュメント内のハイライト参照
  • 自動補完
  • brittany を使ったコード整形
  • HaRe を使った名前変更リファクタリング
  • import 文の自動挿入
  • import 文からパッケージを cabalhpack に追加
  • typo の quick fix
  • hsimport を使った import 文の挿入
  • liquidhaskell のサポート
  • Case splitting

hiehlint, brittany, ghc-mod 等を全てライブラリから扱うことができるため、それぞれのバイナリファイルは必要ありません。(つまり、stack install hlint などでインストールしなくても使えるということです)

hie のデメリット

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

  • プロジェクトごとに異なる hie のバイナリが必要なので、ビルドの時間が長い。またかなりディスク容量を消費します (Wild thought: use ghc-hotswap to load plugins #904 という取り組みも今後の野望として考えているようです)
  • 良くも悪くも安定していないので、master ブランチが壊れている場合があります
  • macOS でメモリ (Memory characteristics questions #412) がありえないほど消費されます。(GHC のバグなのでそのうち直ると思います。Ubuntu では気になったことはありません)

一応、以下のように 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 $@

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

依存関係のインストール

Debian/Ubuntu
$ sudo apt install libicu-dev libtinfo-dev libgmp-dev

Stack のインストール

stackのインストール
$ curl -sSL https://get.haskellstack.org/ | sh

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

stackの更新
$ stack upgrade

パスを通す

すでに設定している方は必要ありません。
だいたいこんな感じです。必要に応じて変更しましょう。

$ echo 'export PATH=$PATH:~/.local/bin' >> ~/.bash_profile
$ source ~/.bash_profile

ビルド済みバイナリ

Mac OS についてはビルド済みのバイナリが配布されています。(現状はまだ安定していないため、ビルド済みバイナリがリリースされていない場合もあります)

releases ページから hie-0.4.0.1-x86_64-Darwin.tar.gz 172 MB をダウンロードして使いましょう。

バイナリファイルのダウンロードとインストール
$ curl -L -O https://github.com/haskell/haskell-ide-engine/releases/download/0.4.0.1/hie-0.4.0.1-x86_64-Darwin.tar.gz
$ tar xzf hie-0.4.0.1-x86_64-Darwin.tar.gz -C ~/.local/bin/

$ ls ~/.local/bin/ | grep hie
hie
hie-8.2
hie-8.2.1
hie-8.2.2
hie-8.4
hie-8.4.2
hie-8.4.3
hie-8.4.4
hie-8.6.1
hie-8.6.2
hie-wrapper

hie-8.6.3 はまだ含まれていないようですね。

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

make コマンドを実行すると、利用可能な GHC のバージョン一覧が表示されます。

$ make
... 初回のみ ghc-8.6.3 のインストールが始まる場合があります ...

$ make

Usage:
  make <target>

Targets:
  build                Builds hie for all supported GHC versions (8.2.1, 8.2.2, 8.4.2, 8.4.3, 8.4.4, 8.6.1, 8.6.2 and 8.6.3)
  build-all            Builds hie and hoogle databases for all supported GHC versions
  hie-8.6.2            Builds hie for GHC version 8.6.2 only
  hie-8.6.1            Builds hie for GHC version 8.6.1 only
  hie-8.4.4            Builds hie for GHC version 8.4.4 only
  hie-8.4.3            Builds hie for GHC version 8.4.3 only
  hie-8.4.2            Builds hie for GHC version 8.4.2 only
  hie-8.2.2            Builds hie for GHC version 8.2.2 only
  hie-8.2.1            Builds hie for GHC version 8.2.1 only
  hie-8.6.3            Builds hie for GHC version 8.6.3 only
  submodules           Updates local git submodules
  cabal                NOTE 3: This is needed for stack only projects too
  build-docs           Builds the Hoogle database for all supported GHC versions
  test                 Runs hie tests
  icu-macos-fix        Fixes icu related problems in MacOS
  dist                 Creates a tarball containing all the hie binaries
  help                 Show help

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

hie のインストール

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

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

通常の良くある stack install コマンドではなく make を使ったインストールを推奨するのは、それらのつまらない作業を全部やってくれるからです。

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

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

全てのバージョンのGHCをインストールする方法

個人的には推奨しません。

$ git clone https://github.com/haskell/haskell-ide-engine --recursive
$ cd haskell-ide-engine
$ make build-all
# ここからビルドのため、30分以上かかります。
...
Copied executables to /home/USER/.local/bin:
- hie

$ make build-docs
...

必要な分だけ個別にインストールする方法

GHC 8.6.3

$ git clone https://github.com/haskell/haskell-ide-engine --recursive
$ cd haskell-ide-engine
$ make hie-8.6.3
$ make build-doc-8.6.3

GHC 8.6.2

$ git clone https://github.com/haskell/haskell-ide-engine --recursive
$ cd haskell-ide-engine
$ make hie-8.6.2
$ make build-doc-8.6.2

GHC 8.6.1

$ git clone https://github.com/haskell/haskell-ide-engine --recursive
$ cd haskell-ide-engine
$ make hie-8.6.1
$ make build-doc-8.6.1

GHC 8.4.4

$ git clone https://github.com/haskell/haskell-ide-engine --recursive
$ cd haskell-ide-engine
$ make hie-8.4.4
$ make build-doc-8.4.4

GHC 8.4.3

$ git clone https://github.com/haskell/haskell-ide-engine --recursive
$ cd haskell-ide-engine
$ make hie-8.4.3
$ make build-doc-8.4.3

GHC 8.4.2

$ git clone https://github.com/haskell/haskell-ide-engine --recursive
$ cd haskell-ide-engine
$ make hie-8.4.2
$ make build-doc-8.4.2

GHC 8.2.2

$ git clone https://github.com/haskell/haskell-ide-engine --recursive
$ cd haskell-ide-engine
$ make hie-8.2.2
$ make build-doc-8.2.2

GHC 8.2.1

$ git clone https://github.com/haskell/haskell-ide-engine --recursive
$ cd haskell-ide-engine
$ make hie-8.2.1
$ make build-doc-8.2.1

GHC 8.0.2

$ git clone https://github.com/haskell/haskell-ide-engine --recursive
$ cd haskell-ide-engine
$ git checkout hie-0.1.0.0
$ stack --stack-yaml=stack-8.0.2.yaml install

shake を使ったビルド方法

$ stack ./install.hs help

GHC 8.6.3

$ stack ./install.hs hie-8.6.3
$ stack ./install.hs build-docs

他のバージョンも同様の方法でインストールできます。

VSCODE の設定

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

$ hie --version
Version 0.5.0.0, Git revision ce022201ee54fc0cf509da7942e228dd0f1b65d9 (2325 commits) x86_64 ghc-8.6.3

hlint

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

"languageServerHaskell.hlintOn": true,
"languageServerHaskell.maxNumberOfProblems": 100,

liquidhaskell

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

"languageServerHaskell.liquidOn": true,

カスタムhieラッパー

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

"languageServerHaskell.useCustomHieWrapper": true,
"languageServerHaskell.useCustomHieWrapperPath": "~/wrapper-in-home.sh",

WINDOWS 環境の場合

PowerShell

build-all.ps1 を利用します。

PowerShell
./build-all.ps1

cmd.exe

cmd.exe
powershell -ExecutionPolicy RemoteSigned -c ./build-all.ps1

詳しくは Installation on Windows をご確認ください。

トラブルシューティング

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

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

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

$ make 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.2)

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

ss2.png

拡張機能の追加

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.3, http://hoogle.haskell.org/

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

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

$ stack haddock --keep-going

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

documentation: True

定義へのジャンプ

jump

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

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

list

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

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

hilight

自動補完

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

complement

コード整形

brittany というツールによってコードを整形します。

formatting

名前の変更

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

hare

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

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

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

phoityne-vscode.gif

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

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

まとめ

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

$ stack build --fast --file-watch

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

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

それと比べれば、敷居がとても低そうなので Haskell で開発したい人にオススメです!
最新の IDE 環境でモダンな Haskell アプリケーション開発を学びましょう!

参考