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