VPS上でのHaskellの開発環境構築

7 min読了の目安(約6400字TECH技術記事

この記事は2020/10/22に書かれたものです。
間違っているところや変なところがありましたらご指摘いただけますと幸いです。

環境構築の動機

私はなかなかPCに向かう時間が取りづらいので、スマホでコードを書いて試せる環境が欲しくなり、サーバー上に開発環境を作ることにしました。
なぜHaskellかというと、私はこの本を読んで関数型プログラミングを学ぼうとしていて、本で使われている言語がHaskellだったからです。
環境構築中に原因不明の不具合に遭遇し、直接的な解決につながる情報が得られず苦しんだため、メモを残しておきます。

構築する環境

  • スマホからSSH接続できる
  • Vimを使ってHaskellのプログラムを書ける
  • HaskellのLanguageServer機能を利用できる
  • Haskellのプログラムをビルドできる
  • Linuxサーバー

手順

VPSを契約してVMインスタンスを作成

https://aws.amazon.com/jp/lightsail

メモリが4GB以上のインスタンスを選択してください。そうしないとLanguageServerが正常に機能しないようです。また、Ubuntu20.04はghcupのインストールの際の必要パッケージのインストールでエラーが発生するため避けた方がわかりやすいです。私はDebian10.5のメモリ4GBを使うことにしました。

別にVPSである必要はないのですが、必要スペックを満たしていて、安く面倒なく済ませようと考えてVPSを選択しました。
VPSにもいくつかありますが、AWS Lightsailを利用することにしました。
SSH接続するための情報はLigitsailでインスタンス情報を参照すると表示されます。また、スマホからSSH接続するためのアプリはいくつかありますので探してみてください。

パッケージリストとパッケージを更新

VPSにSSH接続できたら、まずはパッケージリストとパッケージを更新します。

Ubuntuの例
sudo apt update
sudo apt upgrade

ghcup、ghc、cabal、haskell-language-serverをインストール

Haskellのサイトのおすすめに従い、ghcupを使ってインストールします。
インストールはスクリプトで自動的に行われますが、途中で止まって応答を求めてきます。2回目に止まるところで必要なパッケージが表示されるので、無視せずにスクリプトを一旦止めてインストールしてください。インストールしたあとにもう一度スクリプトを実行します。

インストールコマンド例(Ubuntu,Debianの場合)
sudo apt install 表示されたパッケージ群

haskell-language-serverをインストールするかについても聞かれるのでyesと答えます。

Stackをインストール

Stackのサイトに記載されている通りの順番でインストールします。手順通りに実行すると、最後にHelloWorld的なプログラムが実行することになります。

Vimをインストール

LanguageServerの機能を利用するには、その機能に対応したクライアントが必要になります。
haskell-language-serverのリポジトリではCocを推しているようでしたので、Cocを利用することにしました。
Lightsailのインスタンスに最初からインストールされているVimはバージョンが少し古く、Cocが警告を出してしまうので、新しいバージョンのVimをインストールします。
Vim公式サイトに記載されている手順に沿って自分でビルドします。

Cocをインストール

CocのリポジトリのQuick Startに従い、Node.jsvim-plug、Cocをインストールします。

Node.jsのインストールの際にbashで実行する手順になっていますが、sudoをつけないとエラーが発生します。

haskell-language-serverの設定

Cocの設定

haskell-language-serverのリポジトリに記載された説明の通り、:CocConfigコマンドでCocの設定ファイルを編集します。

プロジェクトごとの設定

haskell-language-serverのリポジトリに記載されている通り、hie.yamlファイルが必要になります。このファイルがないとCocが警告を出します。
hie.yamlファイルを作成するにはツールを使った方が良いようです。

hie.yamlファイルを作成するツール(implicit-hie)のインストール
stack install implicit-hie

動作確認

Vimで拡張子が.hsのファイルを開いてINSERTモードで編集してみてください。
LanguageServerから情報を取得して表示してくれるはずです。
編集画面

失敗の記録

原因不明なものばかりでしたが、メモリを4GBにしたら解決しました…。

メモリが512MBのUbuntu20.04

stack setupでエラー
Downloaded ghc-tinfo6-8.8.4.                                      
ghc-cabal:                                                                             
'/home/ubuntu/.stack/programs/x86_64-linux/ghc-tinfo6-8.8.4/lib/ghc-8.8.4/bin/ghc'
exited with an error:
                  
make[1]: *** [ghc.mk:994: install_packages] Error 1
make: *** [Makefile:51: install] Error 2
Received ExitFailure 2 when running
Raw command: /usr/bin/make install
Run from: /home/ubuntu/.stack/programs/x86_64-linux/ghc-tinfo6-8.8.4.temp/ghc-8.8.4/

                  
Error: Error encountered while installing GHC with
         make install
         run in /home/ubuntu/.stack/programs/x86_64-linux/ghc-tinfo6-8.8.4.temp/ghc-8.8.4/
       
       The following directories may now contain files, but won't be used by stack:
         - /home/ubuntu/.stack/programs/x86_64-linux/ghc-tinfo6-8.8.4.temp/
         - /home/ubuntu/.stack/programs/x86_64-linux/ghc-tinfo6-8.8.4/
       
       For more information consider rerunning with --verbose flag
       
Installing GHC ...

メモリが1GBのUbuntu20.04

stackのインストールは成功しましたが、ghcupのインストールでエラーが発生しました。

ghcupのインストールの際のパッケージのインストールでエラー
$ sudo apt install build-essential curl libffi-dev libffi6 libgmp-dev libgmp10 libncurses-dev libncurses5 libtinfo5
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package libffi6

これはUbuntu20.04固有のエラーのようです。メモリを増やそうともパッケージリストに存在しないのでインストールできません。

ghcupのインストールをそのまま続行してエラー
[ Error ] Build failed with NonZeroExit 1 "./configure" ["--prefix=/home/ubuntu/.ghcup/ghc/
8.8.4"]
    Check the logs at "/home/ubuntu/.ghcup/logs" and the build directory "/tmp/ghcup-EonOAO
" for more clues.
    Make sure to clean up "/tmp/ghcup-EonOAO" afterwards.
"_eghcup --cache install ghc recommended" failed!
Vimのmakeでエラー
no terminal library found
checking for tgetent()... configure: error: NOT FOUND!
      You need to install a terminal library; for example ncurses.
      Or specify the name of the library with --with-tlib.
Makefile:304: auto/config.mk: No such file or directory
make: *** [Makefile:2056: auto/config.mk] Error 

メモリが1GBのDebian10.5(AmazonLnux2も同様の挙動)

各種インストールはできたものの、implicit-hieのインストールでエラーが発生しました。

implicit-hieのインストールでエラー
aeson                > [ 6 of 24] Compiling Data.Aeson.Parser.Internal
aeson                > ghc: internal error: Unable to commit 1048576 bytes of memory
aeson                >     (GHC version 8.8.4 for x86_64_unknown_linux)
aeson                >     Please report this as a GHC bug:  https://www.haskell.org/ghc/re
portabug
Progress 24/30       

--  While building package aeson-1.4.7.1 (scroll up to its section to see the error) using:
      /home/admin/.stack/setup-exe-cache/x86_64-linux-tinfo6/Cabal-simple_mPHDZzAJ_3.0.1.0_
ghc-8.8.4 --builddir=.stack-work/dist/x86_64-linux-tinfo6/Cabal-3.0.1.0 build --ghc-options
 " -fdiagnostics-color=always"
    Process exited with code: ExitFailure (-6)

また、.hsファイルを開いたところ、LanguageServerの起動に失敗したことを表すメッセージが表示されました。

[coc.nvim] Server languageserver.haskell failed to start: Launching server "languageserver.
haskell" using command haskell-language-server-wrapper failed.
Press ENTER or type command to continue

メモリが2GBのDebian

メモリ1GBと同じ挙動でした。

参考記事

https://haskell.e-bigmoon.com/hie/vscode.html