HIW 2019で発表された、GHC 8.10に導入されるであろう機能

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

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

前回から引き続き、Haskell ImplementorsWorkshop 2019への参加レポートとして、私の印象に残った発表をいくつか紹介します。
今回は、「GHC 8.10に導入されるであろう機能」です。
いずれも該当するMerge Requestmasterブランチにマージ済みなので、おそらくGHC 8.10で提供されるでしょう。

Link to
here
HoleFitPlugins and the future of interactive development in GHC

  • 発表者: Matthías Páll Gissurarson Chalmers University of Technology, Sweden
  • 該当のMerge Request: !153
  • 該当のGHC Proposal: なし

昨年のHaskell Symposiumでも発表されてGHC 8.6で導入された、「Valid Hole Fits」という機能のさらなる拡張について。

まず、「Valid Hole Fits」という機能について軽く紹介します(詳しくはこちらのスライドが参考になるかと思います)
Valid Hole Fits」はアンダースコア _で始まる識別子を書いたとき、GHCが推論した型にマッチする関数をエラーメッセージに付記することで、ユーザーがどんな式を書けばよいか、ヒントを与えてくれるものです。

例えば、

map (length . _someFunc) [True, False, True]

上記のように、アンダースコア _で始まる識別子を書いたとき、

<interactive>:1:16: error:
    ...
      Valid hole fits include
        enumFrom :: forall a. Enum a => a -> [a]
          with enumFrom @Bool
          (imported from ‘Prelude’ (and originally defined inGHC.Enum’))
        show :: forall a. Show a => a -> String
          with show @Bool
          (imported from ‘Prelude’ (and originally defined inGHC.Show’))
        repeat :: forall a. a -> [a]
          with repeat @Bool
          (imported from ‘Prelude’ (and originally defined inGHC.List’))
        return :: forall (m :: * -> *) a. Monad m => a -> m a
          with return @[] @Bool
          (imported from ‘Prelude’ (and originally defined inGHC.Base’))
        pure :: forall (f :: * -> *) a. Applicative f => a -> f a
          with pure @[] @Bool
          (imported from ‘Prelude’ (and originally defined inGHC.Base’))
        mempty :: forall a. Monoid a => a
          with mempty @(Bool -> [a0])
          (imported from ‘Prelude’ (and originally defined inGHC.Base’))

といった具合に、アンダースコアで始まる識別子_someFuncの型をBool -> [a0]と推論した上で1、実際にその型に該当する関数を、当該のスコープにおいてアクセスできる関数の中から探して教えてくれる、それが「Valid Hole Fits」という機能です。

今回発表された「HoleFitPlugins」という機能は、名前のとおりこの「Valid Hole Fits」に対するプラグイン機構です。
Valid Hole Fits」が表示する「型にマッチした関数」を探す処理を、Haskellのコードで書き換えられるようにしてくれます!

「そこまでする必要あるの?」という気もしてきますが、発表者曰く

  • Hoogleをはじめ、TensorFlowなどGHCの外部にあるものを利用して「型にマッチした関数」を探せるようにするために必要
  • GHCiとこの機構を組み合わせることで、もっとインタラクティブな開発を促進したい

という意図があるそうです。

最新安定版のGHCでは利用できませんが、ドキュメントがこちらにあるので、GHCHEADmasterブランチで開発中のバージョン)をコンパイルすれば使用できるようです。

加えて発表では、_で始まる識別子を書く際の構文を拡張することで、どのようにcandidateを探すか指定できるようにする、なんて機能も紹介されました(ドキュメントを読む限りこの機能はまだHEADに入ってない?)
例えば、Hoogleを使ってValid Hole Fitsを探したいとき、次のように書くことで検索対象をControl.Applicativeに限定する、といったことをできるようしてくれます。

g :: [a] -> [[a]]
g = _{hoogleLookup "+Control.Applicative"}

Valid Hole Fitsの検索方法をその場で微調整したい、というときに使うものですね。

Link to
here
Visible dependent quantification

  • 発表者: Ryan Scott Indiana University at Bloomington, USA
  • 該当のMerge Request: !378
  • 該当のGHC Proposal: 0081-forall-arrow

タイトルのとおり、「Visible dependent quantification」という機能の紹介です。

最近のバージョンのGHCiにおける:kindコマンドは、次のような、GHCがサポートしていない構文の型注釈を出力することがあります。
例えば

> :set -XKindSignatures
> :set -XPolyKinds
> data SomeType k (a :: k)
> :kind SomeType
SomeType :: forall k -> k -> *

における、SomeType :: forall k -> k -> *forall k ->という部分です。
現在のHaskellforall kなどと書くときは、必ず

SomeType :: forall k. k -> *

といった具合に、ピリオドで区切った構文になります。
ところが先ほどの:kindの出力では、forall k ->とあるとおり、forall k(型ではなく、カインドとしての)関数を表す->が使われています。
Visible dependent quantification」はまさにこれを、:kindコマンドによって出力される構文だけではなく、ユーザーが直接書ける構文にしよう、というものです。 GHCに「依存型」という機能を加える「Dependent Haskell」にも必要な機能だそうです。
私自身はこの機能を使う機会がちょっと思い浮かばなかったので省略しますが、より詳しい解説は発表者であるRyan自身による記事(英語)をご覧ください。何が「Visible」でどう「Dependent」なのかわかるはずです。


  1. 復習: この、「アンダースコアで始まる識別子_someFuncの型をBool -> [a0]と推論した上で」エラーメッセージにおいてFound hole: _someFunc :: Bool -> [a0]と教えてくれるのが「Type Hole」という機能なのでした。↩︎