Haskell
関連記事
Wikipedia から:
- Haskell は高階関数や静的多相型付け、定義可能な演算子、例外処理といった多くの言語で採用されている現代的な機能に加え、パターンマッチングやカリー化、リスト内包表記、ガードといった多くの特徴的な機能を持っている。また、遅延評価や再帰的な関数や代数的データ型もサポートしているほか、独自の概念として圏論のアイデアを利用し参照透過性を壊すことなく副作用のある操作 (例えば 代入、入出力、配列など) を実現するモナドを含む。このような機能の組み合わせにより、手続き型プログラミング言語では記述が複雑になるような処理がしばしば簡潔になるばかりではなく、必要に応じて手続き型プログラミングを利用できる。
インストール
ネイティブインストール
Haskell は、Linux 上でネイティブに実行できるマシンコードを生成します。xmonad や pandoc-cli などのバイナリ (コンパイル済み) ソフトウェアを実行するために特別に必要なものは何もありません。一方、AUR パッケージのビルドやソフトウェアの開発には、コンパイラとビルド ツールをインストールする必要があります。
Haskell の最新バージョンをインストールするには、次のパッケージを インストール します。
- ghc - Haskell コンパイラ。いくつかの 実装 がありますが、最もよく使われている (現在では 事実上 リファレンスとなっている) のは GHC (Glasgow Haskell Compiler) です。
- cabal-install または stack です。- GHC に依存して Haskell ソースをコンパイルするビルドツール。Cabal は依存関係の解決と Hackage (Haskell コミュニティのオープンソースソフトウェアの中央パッケージアーカイブ) からのソースパッケージに焦点を当てた古典的なビルドツールです。Stack は、Stackage (Hackage の安定したサブセットで、互いにうまく動作することが知られているパッケージのキュレーションセット (スナップショット) を提供する) のキュレーションされたスナップショットとソースパッケージに焦点を当てた別のビルドツールです。
設定
バージョン 8.0.2-1 以降、extra に含まれる Arch ghc パッケージと全ての haskell-* パッケージは動的にリンクされるライブラリのみを提供します。そのため、リンクに成功するためには GHC, Cabal, Stack を動的リンクに設定する必要があります。
動的リンクを使用すると、通常、(実行中の複数の Haskell プログラム間でページを共有することにより) ビルドが高速化され、ディスクと RAM の使用量が削減され、GHC 間の混合エラーのトラブルシューティングから解放されます。しかし、これには独自の欠点もあります。それは、ghc、ghc-libs、または org/packages/?q=haskell haskell-* パッケージは、GHC でコンパイルされたライブラリが安定した ABI を提供しないためです。このような壊れたバイナリを実行すると、通常のメッセージ error whileloadingsharedlibraries:libHS...so:cannotopensharedobjectfile:No such file or directory
が表示されます。これを修正するには、壊れたツールを再構築して再インストールし、新しいライブラリに再リンクします。
一方、静的リンクは一般に保守が容易で、依存関係を更新するたびにすべてのツールをソースから再構築する必要がありません。これらの理由から、静的リンクは、パッケージシステム外のローカル開発では多くの場合推奨されるオプションです。 静的リンクを希望する場合、詳細については 静的リンク または 代替インストール を参照してください。
GHC を直接呼び出す
正常にリンクするには、-dynamic
フラグを GHC に渡す必要があります。次のファイルで試すことができます。
Main.hs
main = putStrLn "Hello, World"
次のようにコンパイルして実行します。
$ ghc -dynamic Main.hs $ ./Main
Hello, World
Cabal を動的リンク用に構成する
まず、次のコマンドを実行して、Hackage からパッケージの最新リストをダウンロードし、グローバル設定ファイル ~/.cabal/config
(または、$CABAL_CONFIG
が指すファイル) を作成します。
$ cabal update
Cabal を動的リンク用に設定するには、~/.cabal/config
内の次のオプションのコメントを解除して編集します。
~/.cabal/config
library-vanilla: False shared: True executable-dynamic: True program-default-options ghc-options: -dynamic
library-vanilla: False
は静的ライブラリの作成を抑制します (プロジェクトにライブラリが含まれている場合)shared: True
は共有ライブラリの作成を有効にします(プロジェクトにライブラリが含まれている場合)executable-dynamic: True
は実行ファイルにダイナミックリンクを使用します (プロジェクトに実行ファイルが含まれている場合)ghc-options: -dynamic
は GHC の全ての呼び出しに-dynamic
フラグを追加します (例えば、パッケージが自明でないSetup.hs
を持っている場合)
動的リンク用のスタックの設定
stack setup
コマンドを使用してスタックを初期化し、グローバル設定ファイル ~/.stack/config.yaml
を作成できます。デフォルトでは、スタックは最初の呼び出し時に独自のバージョンの GHC を隔離された場所に自動的にダウンロードします。代わりにスタックにシステム GHC インストールを使用させるには、--system-ghc
フラグと --resolver
フラグを指定して stack setup
を実行します。
$ stack setup --system-ghc --resolver resolver
システムの GHC と互換性のあるリゾルバーを指定する必要があることに注意してください。それ以外の場合、スタックは --system-ghc
フラグを喜んで無視し、GHC の独自のコピーをダウンロードします。システム GHC のバージョンは、ghc --version
コマンドを使用して確認できます。
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.10.2
次に、Stackage Web サイトにアクセスし、システムの GHC バージョンに一致する適切な長期サポート (LTS) または夜間スナップショットを選択します。コマンドラインの --resolver
フラグに対して選択したスナップショットを使用します。例:--resolver lts-16.15
または --resolver nightly-2020-09-01
Stackage は通常、新しい GHC リリースより遅れます。システム GHC のスタックスナップショットがまだリリースされていない場合があります。この場合、GHC の以前のマイナーバージョンのスナップショットを選択するか、Haskell インストールを一時的にダウングレードして、新しい GHC リリースのサポートが最終的に Stackage に提供されるまで待つことをお勧めします。
動的リンク用にスタックを構成するには、次のスニペットを ~/.stack/config.yaml
に追加します。
~/.stack/config.yaml
# Stop downloading GHCs into isolated locations under ~/.stack. install-ghc: false # Allow Stack to pick the system GHC (false by default). system-ghc: true # Allow to use, say, Stackage snapshot for GHC 8.8.2 with system GHC 8.8.3. compiler-check: newer-minor # Add the -dynamic flag to every invocation of GHC. ghc-options: "$everything": -dynamic
Haskell パッケージの管理
Haskell のライブラリと実行可能ファイルのほとんどは、Hackage および Stackage から入手できるソースパッケージの単位で配布されます。
他のコンパイル言語では一般的なことですが、多くの人気のある Haskell パッケージは、事前構築された形式で公式 Arch リポジトリから入手できます。いくつかの追加パッケージは AUR からインストールできます。
GHC、ライブラリ、およびツールをインストールするには pacman を使用することが推奨されますが、ある時点で、Hackage/Stackage から直接 Haskell パッケージをインストールしたり、ソースから独自の (または他の人の) パッケージをコンパイルしたくなるかもしれません。これを行うには、Cabal または Stack が必要になります。
次の表は、さまざまなパッケージ管理スタイルの長所と短所をまとめたものです。
方法 | 良い点 | 悪い点 |
---|---|---|
公式リポジトリ | ArchLinux 開発者が運営、パッケージのバージョンの整合性に問題なし、コンパイル済み | 利用できるパッケージの数が限られる、動的ライブラリのみ |
cabal-install | 全てのパッケージが利用可能、root 権限が不要 | インストール先がホームフォルダ、cabal-install はパッケージマネージャではない、パッケージのバージョンの整合性に問題がある可能性 (別名 cabal hell) |
stack | (Stackage にある) 全てのパッケージが利用可能、root 権限が不要 | インストール先がホームフォルダで、バージョンがスナップショットに固定、特定のパッケージを削除するのは難しい |
Arch User Repository | 始めるのが簡単 | パッケージのメンテナンスがなくなる可能性、パッケージのバージョンの整合性に問題がある可能性 |
cabal
Cabal は Haskell の "オリジナル" のビルドシステムです。Hackage で見つかるライブラリやツールのほとんどは、Cabal 経由でインストールできます。
パッケージのインストール
Cabal によってインストールされたユーザー全体の実行可能ファイルを実行するには、~/.cabal/bin
を $PATH
環境変数 に追加する必要があります。
PATH="$HOME/.cabal/bin:$PATH"
次のコマンドを実行して、Hackage パッケージとそのすべての依存関係を 1 つのステップでインストールします。
$ cabal install --ghc-options=-dynamic package
Haskell パッケージをソースからビルドしてインストールすることもできます。これを行うには、パッケージディレクトリから次のコマンドを実行します。
$ cabal install --ghc-options=-dynamic
各 Cabal パッケージは、パッケージ バージョン管理ポリシー (PVP) に従って、依存関係のリストとそのバージョン制約を .cabal
ファイルに指定する必要があります。パッケージのインストール中に、Cabal はすべての制約を満たす一連の依存関係を見つけようとします。このプロセスは 依存関係の解決 と呼ばれます。
スタックが存在するのには理由があります。cabal は初心者との間に多くの軋轢を生むことで知られています。ほとんどの場合、依存関係の解決はうまく機能しますが、失敗する場合もあります。この場合、問題の原因を突き止め、問題のある依存関係を解決する方法について Cabal にヒントを与える必要があります。たとえば、場合によっては、Cabal がパッケージの PVP によって規定された依存関係の上限を無視できるようにするために、cabal install --allow-newer --ghc-options=-dynamic package
と言う必要があります。バージョンを変更し、パッケージ作成者が許可したものよりも新しい依存関係を持つパッケージを効果的にインストールします。 あまり適切に管理されていないパッケージの場合は、さらに面倒になります。別の例については、Idris (Haskell で書かれた別のプログラミング言語) のインストールに関する このスレッド を参照してください。--allow-newer
および --constraint='haskeline < 0.8.0.0'
コマンドラインフラグを使用してコンパイルを成功させます。
パッケージの削除
簡単な方法はありません。 Cabal はこの機能をサポートしていませんが、cabal-store-gc のような外部ツールがあります。
ユーザー全体の Haskell パッケージ システム全体を再インストールするには、~/.cabal
と ~/.ghc
を削除して、最初から始めます。これは、GHC をアップグレードするときに必要になることがよくあります。
より正確に行うには、ghc-pkg unregister package
または ghc-pkg hide package
/ghc-pkg expose package
を user package database 上で直接使うことができます。しかし、どちらもファイルを削除しません。
Stack
Stack は、Haskell パッケージを管理するためのもう 1 つのツールです。それは cabal とは少し異なる目標を持ち、少し異なる哲学を持っています。これは内部で Cabal ライブラリを使用し、Hackage と統合します。ただし、スナップショットが厳選され、連携して適切に動作するパッケージが含まれることを約束して、独自のパッケージ (スナップショット) リポジトリを Stackage 上に維持します。
パッケージのインストール
デフォルトの設定では、Stack はコンパイル済みの実行ファイルを ~/.local/bin
にインストールします。このディレクトリをシェル設定ファイルの $PATH
環境変数に追加してください。例えば bash なら ~/.bashrc
、zsh なら ~/.zshrc
です:
export PATH="$HOME/.local/bin:$PATH"
次のコマンドを実行して、Stackage パッケージをダウンロード、ビルド、インストールします。
stack install package
パッケージディレクトリから次のコマンドを実行して、ソースから Haskell パッケージをビルドしてインストールすることもできます。
stack install --resolver resolver
stack setup
コマンドで使用したものと同じリゾルバーを指定する必要があることに注意してください。
パッケージの削除
スタックは "アンインストール" 操作をサポートしていません。
ユーザー全体の Haskell パッケージシステム全体を再インストールする場合は、~/.stack
ディレクトリを削除して、最初から始めてください。これは、GHC をアップグレードするときに必要になることがよくあります。
開発ツール
ツール
haskell-language-server
haskell-language-server は、Haskell の 言語サーバープロトコル (LSP) 実装です。これは、コード補完、"定義に移動"、ホバーに関するドキュメント、リンティング、書式設定、または LSP と統合されたエディターのリファクタリングなどの IDE のような機能を提供します。
pacman から動的にリンクされた Haskell パッケージを使用している場合は、haskell- language-server をインストールします。それ以外の場合、静的リンクを希望する場合は、haskell-langage-server-staticAUR をインストールしてください。このパッケージには、サポートされている GHC バージョンごとに静的にリンクされたバイナリが含まれています。あるいは、haskell-language-server は ghcup 経由、または Visual Studio Code の Haskell 拡張機能 によってインストールできます。
haskell-language-serverは、プロジェクトを開いたときに自動的にビルド構成を決定しようとします。自動判別に失敗した場合は、プロジェクトのルートディレクトリにある hie.yaml
ファイルを使って 手動で設定する とよいでしょう。
ghcid
ghcid は、Haskell 開発用の GHCi ベースのツールです。は、ソースコードの変更ごとにコンパイラエラーと警告を表示するシンプルかつ堅牢な方法を提供します。ghcidAUR パッケージ経由でインストールできます。
hoogle
hoogle を使用すると、関数名またはおおよその型シグネチャによって Haskell ライブラリを検索できます。hoogle パッケージ経由でインストールできます。
hoogle のオンライン版は https://hoogle.haskell.org で入手できます。
リンター
hlint
hlint は、代替関数の使用、コードの簡素化、冗長性の特定など、Haskell コードの改善の可能性を示唆しています。これは、hlint パッケージを通じて入手できます。
stan
stan は、hlint を補完する Haskell 静的アナライザーです。2021 年 6 月現在はベータ段階です。
weeder
weeder はプログラム全体のデッドコード解析を行うアプリケーションです。
フォーマッタ
- brittany — Haskell ソースコードフォーマッタ
- Floskell — 柔軟性と設定可能性に焦点を当てた hindent のフォーク
- fourmolu — 様々な書式パラメータを設定する機能を追加した Ormolu のフォーク
- hindent — 拡張可能な Haskell プリンター
- Ormolu — Haskell ソースコード用のフォーマッタで、設定を必要としない "真の" 書式スタイルを実装しています。
- stylish-haskell — シンプルな Haskell コードの整形ツール。
エディタ
Visual Studio Code
Visual Studio Code には、haskell-language-server を利用した Haskell 拡張機能 があります。haskell-language-server がインストールされていない場合は、Haskell 拡張機能が静的にリンクされた Linux バイナリを自動的にダウンロードしてインストールします。
IntelliJ IDEA
IntelliJ IDEA Haskell のサポートは、Haskell プラグイン によって提供されます。 intellij-idea-community-edition を含む IntelliJ IDEA のどのエディションでも動作します。
新しいプロジェクトを作成するか、既存のプロジェクトを IntelliJ IDEA にインポートするには、Stack をインストールする必要があります。2021 年 6 月現在、Cabal のみのプロジェクト はサポートされていません
Vim
Vim の基本的な設定のハイライトとインデントは、haskell-vim プラグインを介して取得できます。IDE のようなエクスペリエンスを向上させるには、LSP client プラグイン (例:coc.nvim、ALE、LanguageClient-neovim) と haskell- language-server
Emacs
Haskell の基本的な Emacs サポートは、公式 haskell-mode によって提供されます。より高度な機能については、lsp-haskell を haskell-language-server とともに使用してください。
代替インストール
汎用 Linux ディストリビューションに Haskell をインストールするには、ghcup と Stack という 2 つの公式に推奨される方法があります。どちらの方法でも、静的にリンクされた GHC、ツール、ライブラリがホーム ディレクトリにインストールされます。
公式リポジトリの Haskell パッケージの代わりに ghcup または Stack を使用する利点は、複数のバージョンの GHC を並べてインストールして管理できることです。この方法でインストールされた Cabal と Stack は通常、追加の設定を行わずにすぐに動作するため、初心者にとっては簡単かもしれません。
Haskell をインストールするまったく異なる方法は、Nix パッケージ マネージャーです。Nix は学習曲線がより急峻ですが、Haskell パッケージと非 Haskell パッケージの両方を信頼性が高く再現可能な方法で管理する上でより高い柔軟性を提供します。
ghcup
ghcup は、GHC の複数のバージョンを簡単にインストールし、それらを切り替えることができるコマンドラインツールです。これは、[1]、pyenv、および jenv とスコープが似ています。
ghcup-hs-binAUR パッケージをインストールしてください。あるいは、公式の インストール手順 に従うか、手動で ghcup バイナリ をダウンロードして $PATH
のどこかに置いてください。
デフォルトでは、ghcup は GHC 実行ファイルを ~/.ghcup/bin
にインストールします。このディレクトリをシェル設定ファイルの $PATH
環境変数に追加する必要があります。例えば bash なら ~/.bashrc
、zsh なら ~/.zshrc
です。Cabal によってインストールされた実行可能ファイルを実行したい場合は、~/.cabal/bin
も $PATH
に追加してください:
export PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$PATH"
ghcup は、その機能のほとんどをサポートする便利な TUI を提供します。
$ ghcup tui
あるいは、次の CLI コマンドを使用することもできます。
GHC と Cabal の利用可能なバージョンをリストします。
$ ghcup list
推奨バージョンの GHC をインストールします。
$ ghcup install ghc
たとえば、GHC の特定のバージョンをインストールすることもできます。
$ ghcup install ghc 8.10.2
上記のコマンドでは、GHC が $PATH
で自動的に利用可能になるわけではありません。デフォルトで使用する GHC バージョンを選択する必要があります。
$ ghcup set ghc 8.10.2
Cabal の推奨バージョンをインストールします。
$ ghcup install cabal
Cabal を使用して、特別な設定やコマンドラインフラグを必要とせずに、静的にリンクされた Haskell 実行可能ファイルをビルドおよびインストールできるようになりました。
$ cabal update $ cabal install executable
新しい Cabal プロジェクトを開始するには:
$ cd /path/to/my-project $ cabal init $ cabal build $ cabal run
Up to date Hello, Haskell!
haskell-language-server をインストールするには、次のコマンドを使用します。
$ ghcup install hls
詳細については、公式 ghcup および Cabal ドキュメントを参照してください。
Stack
stack-staticAUR パッケージをインストールします。あるいは、公式の インストール手順 に従うか、スタックバイナリ を手動でダウンロードして、それをあなたの $PATH
に配置することもできます。
スタックによってインストールされた実行可能ファイルを実行したい場合は、シェル設定ファイルの $PATH
環境変数に ~/.local/bin
ディレクトリを追加します (例:<code~/.bashrc>~/) bash の場合は、{ic zsh の場合は ~/.zshrc
:
export PATH="$HOME/.local/bin:$PATH"
stack setup
を実行して、最新のスタック LTS スナップショットから GHC を自動的にインストールします。
$ stack setup
特別な設定やコマンドラインフラグを必要とせずに、Stack を使用して静的にリンクされた Haskell パッケージを構築およびインストールできるようになりました。
$ stack install package
詳細については、公式 Stack ドキュメント を参照してください。
Nix
ヒントとテクニック
静的リンク
静的リンクを使用するには、少なくとも、ghc-static パッケージを通じて静的ブートライブラリをインストールする必要があります。これにより、ブートライブラリだけでなく、公式リポジトリから haskell-*
パッケージを通じてインストールされない他のライブラリにもっぱら依存するプロジェクトをビルドできるようになります。
残念ながら、プロジェクトがインストールした動的にリンクされた haskell-*
パッケージのいずれかに依存している場合、Cabal は依存関係の解決時に静的ライブラリの不在を考慮しません。その結果、既存の haskell-*
パッケージを使用しようとし、静的ライブラリを検出すると linker errors で失敗します。:
Could not find module ‘SomePackage.SomeModule’ There are files missing in the ‘somepackage-0.1.0.0’ package, try running 'ghc-pkg check'. Use -v (or `:set -v` in ghci) to see a list of the files searched for.
ghc-static
とは異なり、連携可能な "haskell-*-static
" パッケージはありません。ただし、以下の各セクションで説明するように、この問題を回避する他の方法もあります。
静的グローバルパッケージデータベース
直接的な アプローチ は、公式の ghc-static パッケージによって提供されており、代替の "静的" パッケージが公開されています。グローバルパッケージデータベース(/usr/lib/ghc-version/static-package.conf.d
)静的データベースは、静的にリンク可能なブートパッケージのみに制限されているため、デフォルトデータベースの代わりに静的データベースを使用するように Cabal が再構成されている場合、動的専用の haskell-*
パッケージがリンクされていないかのように動作します。
静的データベースの正確なパスは、次のようなコマンドを使用して構築時に決定できます。
$ ghc --print-global-package-db | sed 's/\(package\.conf\.d\)$/static-\1/'
/usr/lib/ghc-version/static-package.conf.d
静的データベースを使用できるようにする方法は次のとおりです。
- Cabal でパッケージを構築する場合、次のフラグを渡すと、グローバルパッケージの選択をブートパッケージのみに制限できます。
$ cabal configure --ghc-pkg-option="--global-package-db=$(ghc --print-global-package-db | sed 's/\(package\.conf\.d\)$/static-\1/')"
- Cabal ではなく GHC を使用して直接ビルドする場合、次のフラグを渡してグローバルパッケージデータベースをオーバーライドできます。
$ ghc -clear-package-db -package-db "$(ghc --print-global-package-db | sed 's/\(package\.conf\.d\)$/static-\1/')" -user-package-db ...
ghc-pristine
ghc-pristineAUR パッケージをインストールします。このパッケージは既存の GHC インストールをラップして、ブートライブラリのみを含むパッケージデータベースを備えた別の GHC ディストリビューションを /usr/share/ghc-pristine
に作成します。これにより、動的にリンクされた haskell-*
パッケージを使用せずに半分離環境が効果的に作成されますが、それでも公式リポジトリの GHC コンパイラーが利用されます。次に、静的リンクを使用してソフトウェアを構築するには、ラップされたコンパイラー /usr/share/ghc-pristine/bin/ghc
を呼び出すだけです。Cabal の場合、これは ~/.cabal/config
の次の構成に相当します。
~/.cabal/config
with-compiler: /usr/share/ghc-pristine/bin/ghc
プロジェクトディレクトリから次のコマンドを実行して、プロジェクトごとにコンパイラへのパスを指定することもできます。
$ cabal configure --with-compiler=/usr/share/ghc-pristine/bin/ghc
cabal-static
Arch で静的リンクを取り戻すもう 1 つの方法は、cabal-staticAUR パッケージをインストールすることです。公式の cabal-install とは異なり、これは動的にリンクされた haskell-*
の依存関係を公式リポジトリから取得せず、同じシステムにインストールされた静的 Haskell ライブラリと共有 Haskell ライブラリの混合を回避します。その後、次の制限付きで通常どおり Cabal を使用できます: インストールした他の Haskell パッケージが ghc、ghc-libs のみであることを確認する必要があります。および ghc-static (cabal-install、stack、および公式リポジトリで入手可能な haskell-*
パッケージではありません。)
stack-static
stack-staticAUR パッケージをインストールします。cabal-static
メソッドと同様に、公式リポジトリからインストールした他の Haskell パッケージが ghc、ghc-libs、および ghc-static のみであることを確認してください。次に、動的リンク用のスタックの設定 で説明されているように、システム GHC を使用するようにスタックをセットアップします。
$ stack setup --system-ghc --resolver resolver
これらのオプションを永続的にするには、次のスニペットを ~/.stack/config.yaml
に貼り付けます。
~/.stack/config.yaml
# Stop downloading GHCs into isolated locations under ~/.stack. install-ghc: false # Allow Stack to pick the system GHC (false by default). system-ghc: true # Allow to use, say, Stackage snapshot for GHC 8.8.2 with system GHC 8.8.3. compiler-check: newer-minor
この設定では、通常と同じように静的にリンクされたパッケージをビルドできますが、Stack によって提供される GHC の代わりにシステム GHC インストールを使用します。
hpack-static-bin
hpack-static-binAUR は、haskell-hpack の代わりに静的にリンクされた (haskell-*
依存関係がないことを意味します) を提供します。プリコンパイルされているため、make 依存関係は必要ありません。
参照
- Official website of the Haskell programming language
- Haskell documentation
- Haskell Wiki
- GHC User Guide
- Cabal User Guide
- Stack User Guide
- Haskell community's central package archive
- Stable source of Haskell packages
- Haskell API search engine
- Learn You a Haskell for Great Good!
- Real World Haskell
- Haskell Wikibook
- What I Wish I Knew When Learning Haskell
- Awesome Haskell: an auxiliary list of awesome Haskell links, frameworks, libraries and software