HIW 2019で発表された、GHC 8.8で導入された機能

~HIW 2019参加レポート その1~

Posted by Yuji Yamamoto(@igrep) on September 11, 2019Tags: GHC, Haskell Implementors' Workshop

こんにちは。
今回からいくつか、「Haskell ImplementorsWorkshop 2019」に私が先月参加した際のレポートとして、印象深い発表をテーマごとに分けた短い記事を執筆します。
最近公開されたGHC 8.8の話はもちろん、未来のGHCやその他のHaskellの処理系を知るのによいイベントでしたので、その一部だけでも伝われば幸いです。

Link to
here
そもそもHaskell ImplementorsWorkshop (HIW)とは?

シリーズ(?)第1回目なので、簡単にHIWそのものについて紹介しておきましょう。
HIWは、ICFP (International Conference on Functional Programming)という関数型プログラミングについての国際会議に併設された、Haskellの実装者のためのワークショップです。
名前の通り、GHCをはじめとするHaskellの処理系(あるいは、Haskellで実装された言語処理系)の実装に関する発表だけでなく、かなり緩いテーマのLightning Talkの時間があったり、GHCの将来の方向性について自由に議論する時間もあったりしました。

今回はそのうち、掲題のとおり「HIW 2019で発表された、GHC 8.8で導入された機能」を紹介します。まずは「HIE files in GHC 8.8」から。

Link to
here
HIE files in GHC 8.8

発表者: Zubin Duggal, Matthew Pickering University of Bristol

GHC 8.8で新たに追加された、HIE(「Haskell Interface Extended」の略と思われます)ファイルについての発表です。
コンパイル時にGHCが得たモジュールの情報を、Haskell IDE EngineなどのIDEのバックエンドが再利用しやすい形で出力する機能です。
従来Haskell IDE Engine(その裏で使われているghc-modghcidinteroなどの、「IDEバックエンド」(エディターが入力の補完や入力したソースコードにおけるエラーを表示する際に通信するソフトウェア)は、自前でGHC APIGHCiを呼ぶことで、型チェックしたり定義ジャンプに必要な位置情報を収集したりしていたのですが、そうした情報の収集をすべてGHC自身がHIEファイルを出力することで賄えるようになる、ということです。

私は従来開発中、stack test --pedantic --file-watchなどとNeovimのターミナル機能で実行して実行ファイルをビルドしつつ、HIEにエラーの表示や入力の補完をさせていたのですが、その際も二重にソースコードが解析されていたんですね!
私がそのようにわざわざstack testHIEを並行して実行させているのは、HIEがしばしばフリーズしてしまったりNeovimごと再起動すれば直ることも多いんですが…😰)HIEだけでは実行ファイルの作成やテストの実行ができない、という理由があるためです。
stack testだけでHIEファイルが生成されるようになれば、エラーに関する情報やソースコードの解析結果といった情報が一元化されるので、より安定的に、より少ないリソースでHIEが使えるようになるでしょう。本家Haskell IDE Engineがサポートする日が楽しみです。

この、HIEファイルを利用するアプリケーションの例も紹介されました。
hie-lspという小さなLanguage Server Protocolの実装に加え、hie-lsifという、HIEファイルから「Language Server Index Format (LSIF)」形式のファイルを作成するコマンドが印象的でした。
このLSIFというファイルは、例えばGitHubのリポジトリ上でブラウザからソースコードを閲覧する際にも、定義ジャンプといった便利な機能を使えるようにするためのものです。リポジトリに置いたソースコードを処理系がどのように解釈したかを保存しておくことで、Language Serverはじめ処理系を実行することなく利用できるようにするものだそうです。
現状は仕様策定中なためか、実際にLSIFを解釈するアプリケーションは見つかりませんでしたが、今後の活用に期待が高まりますね。

加えて、HIEファイルが将来的にサポートしたい機能などについても発表されました。

  • 型クラスのインスタンスが、具体的にどの型のインスタンスとして解決されたかの出力
    • 定義ジャンプしたときに、型クラス自身の宣言ではなく、実装に飛べるようにするため
  • 従来GHCが分割コンパイルをサポートするために、モジュールの依存情報を出力していた「インターフェースファイル.hiという拡張子で出力されているあのファイル)」との統合
  • すべての型推論の結果

Link to
here
GHC status report

発表者: Simon Peyton Jones Microsoft, UK

GitLabへの移行やHadrianと呼ばれる新しいビルドシステムの導入など、インフラ周りでいろいろ変更があったこともあり、遅れてしまいましたがGHC 8.8がもうすぐ出るよ、という内容の発表でした(発表当時。もうGHC 8.8はリリースされています

言及された主な追加機能は以下のとおりです。

  • TypeApplicationsという言語拡張が、型変数だけでなくカインド変数に対しても適用できるようになりました。
    正直に言って、個人的に使いどころがまだまだなさそうな機能ではありますが…。

  • ScopedTypeVariablesという言語拡張を使った場合に、パターンマッチした変数に型注釈を付けることができるようになる、という機能がありまして、これが拡張されました。
    具体的には、従来下記のように書くことで、関数自体の型注釈にある型変数aと、パターンマッチした変数xに型注釈したbが等しくなるように書くことができたのを、

    f :: forall a. Maybe a -> Int
    f (Just (x :: b)) = {- ... -}

    さらに拡張して、関数自体の型注釈にある型変数ではないIntと、パターンマッチした変数xに型注釈したbが等しくなるように書くことができるようにした、という拡張です。
    あたかも型変数でパターンマッチしているかのようですね。

    f :: Maybe Int -> Int
    f (Just (x :: b)) = {- ... -}

    一体何の役に立つの?とも思いましたが、この修正に向けた提案曰く、

    f :: ReallyReallyReallyReallyLongTypeName -> T
    f (x :: a) = … (read "" :: a) …

    と書くことで、長い型名に対して別名を付けることができるようになる、というメリットがあるそうです。なるほど💡

Link to
here
とりあえず今回はここまで

テーマを絞って短い記事にした方がSEO的にいいんじゃないかと思いまして、今回は敢えて紹介する発表を絞りました。
今後は下記のテーマについて紹介する予定です。

  • HIW 2019で発表された、これからのGHCに入るであろう機能
  • HIW 2019で発表された、GHC以外の言語処理系

また、HIWと同じくICFP 2019に併設して開催された、Haskell Symposium 2019の発表についても別途共有する予定です。
乞うご期待。
hask(_ _)eller