GHC 9.4の新機能
GHC 9.4.1が2022年8月7日にリリースされました(GHC 9.4.1 released — The Glasgow Haskell Compiler)。
この記事では、GHC 9.4の新機能を確認していきます。過去の類似の記事は
です。
GHC 9.4に入る機能
ここでは筆者が独断と偏見で選んだ変更をリストしています。公式の変更リストは
- 2.1. Version 9.4.1 — Glasgow Haskell Compiler 9.4.1 User's Guide
- Changelog for base-4.17.0.0 | Hackage
- Migration Guide 9.4 · Wiki · Glasgow Haskell Compiler / GHC · GitLab
を参照してください。
リリース管理のやつ:
- 9.4.1 release tracking (#21127) · Issues · Glasgow Haskell Compiler / GHC · GitLab
- 9.4.1 · Milestones · Glasgow Haskell Compiler / GHC · GitLab
型の等価性 ~ が普通の型演算子になる
従来のGHCでは GADTs 拡張または TypeFamilies 拡張を有効にすると型演算子 ~ が使えるようになり、 a ~ b という制約で「型 a と型 b が等しい」ことを表現できました。
GHC 9.4では、 ~ の扱いが次のように変わります:
- 使用に
TypeOperators拡張が必要になる(一方で、GADTsやTypeFamiliesは必要なくなる)- 当面の間、
TypeOperatorsなしで~を使った場合は警告が出る
- 当面の間、
-
~はPreludeおよびData.Type.Equalityからエクスポートされるようになる - (
Preludeからエクスポートされる定義を隠せば)~という名前を持ったユーザー定義の型演算子を定義できるようになる
\cases
LambdaCase 拡張の下で \cases という構文が使えるようになります。複数の引数にマッチさせることができます。
例えば
{-# LANGUAGE LambdaCase #-}
f = \cases
(Left a) (b,c) -> a + b + c
(Right a) (b,c) -> a * b + c
という感じです。
DeepSubsumption 拡張
GHC 9.0でsimplified subsumptionという変更が行われました。詳しくは
を見てください。
simplified subsumptionでは手動でη変換が必要になる場面が増えました。これはコンパイルの簡略化のためですが、手動でのη変換はやっぱり面倒なものです。
DeepSubsumption はsimplified subsumption以前の挙動を復活させます。これにより、自動でη変換される場面が増えます。
Haskell2010 の下では DeepSubsumption はデフォルトで有効、 GHC2021 の下では DeepSubsumption はデフォルトで無効です。
DeepSubsumption はGHC 9.2.4にもバックポートされています。GHCのマイナーリリースで新しくGHC拡張が実装されるのは異例のことです(GHC 9.2系がLTSということもあるのでしょうけど)。
ByteArray と MutableByteArray
- Data.Primitive.ByteArray.ByteArray + instances in base? (#20044) · Issues · Glasgow Haskell Compiler / GHC · GitLab
- Add Data.ByteArray (!6152) · Merge requests · Glasgow Haskell Compiler / GHC · GitLab
- Rename Data.ByteArray to Data.Array.Byte + add Trustworthy (!6742) · Merge requests · Glasgow Haskell Compiler / GHC · GitLab
- Export MutableByteArray from Data.Array.Byte (!7785) · Merge requests · Glasgow Haskell Compiler / GHC · GitLab
GHCにはヒープで管理されたバイト列を表すプリミティブ型として ByteArray# 型および MutableByteArray# 型があります。これらはunliftedな型で普段使いには辛いので、liftedなラッパーがprimitiveパッケージなどで提供されていました。
今回、GHC付属のbaseパッケージでliftedなラッパーが提供されることになります。将来、primitiveパッケージが提供する型はbaseパッケージの再エクスポートになるかもしれません。
Levity-polymorphic arrays
GHC.Exts の Array# 型のカインドが
type Array# :: Type -> UnliftedType
から
type Array# :: TYPE ('BoxedRep l) -> UnliftedType
へ一般化されました。これによって、 Array# の要素として通常の型の他にunliftedな型(サンクを許容しない型)が使えるようになります。
これまでは ArrayArray# 型というunliftedな配列の配列みたいな組み込み型がありましたが、それが不要になります。
まあ名前に # のつく型なので一般ユーザーにはあまり影響はないかもしれません。
ST が MonadFail のインスタンスじゃなくなる
MonadFail の趣旨はdo構文中のパターンマッチ失敗時に暗黙に error を発生させるのをやめよう、という感じのやつでした。
ですが、 ST モナドはこの趣旨に反して fail = error な MonadFail インスタンスを持っていました。今回、これがなくなります。
ST モナドで失敗しうるパターンマッチを使っていた人は明示的にパターンマッチして error を呼ぶか、irrefutable patternを使うように書き換える必要があります。
magicDict が withDict になる
型クラスのインスタンスを動的に作れると便利なことがあります。型レベル自然数の辞書である KnownNat のインスタンスを Natural 型の値から作る、というようなやつです。
従来はこれをやるのにGHC組み込みの magicDict を使うか、みんな大好き unsafeCoerce を使うやり方がありました。base では magicDict が、reflection や singletons 等のサードパーティーのライブラリーでは unsafeCoerce が好まれていた印象です。しかし、unsafeCoerce が遅くなる変更が最近(GHC 9.0)入ったため、サードパーティーも magicDict を使うようにしようという機運が高まりました。
ですが、 magicDict の型は
magicDict :: a
という情報量皆無な代物で、正しく使うのは大変でした。GHC 9.4では magicDict が
withDict :: meth -> (cls => r) -> r
に置き換えられることになりました。
Int64/Word64 の内部表現が変わる
Word64 型の定義は、従来は
-- 32ビット環境
data Word64 = W64# Word64#
-- 64ビット環境
data Word64 = W64# Word#
でした。今回、これが
data Word64 = W64# Word64#
に統一されます。GHC 9.2では Word8, Word16, Word32 について似たような変更がありましたね。
Int64 についても同様です。
SPARC NCGの削除
前にこんな記事を書きましたが
SPARC NCGがついに削除されました。
xorとシフト演算子の追加
Haskellでのビット論理和とビット論理積はそれぞれ (.|.) と (.&.) ですが、排他的論理和 (xor) やシフトは xor や shiftL/shiftR という風にアルファベットの名前がついていました。
今回、 xor と shiftL/shiftR に対応する記号の演算子が追加されました。他の関数や演算子のように Data.Bits からエクスポートされます。
-
(.^.)(infixl 6):xor -
(.>>.)(infixl 8):shiftR -
(.<<.)(infixl 8):shiftL -
(!>>.)(infixl 8):unsafeShiftR -
(!<<.)(infixl 8):unsafeShiftL
その他
他にも
- Windows上でClangベースのツールチェインを使う
-
Semigroup,Monoidをderiveするのに便利なGenerically,Generically1- Haskellでの型レベルプログラミングの「応用:GHC.Generics」により詳しい説明を書きました。
- multiple home packages
-
system-cxx-std-lib疑似パッケージ -
-dlintオプション -
OPAQUEプラグマ
などなど新機能がありますが、今回の記事はこの辺にしておきます。
Discussion