GHC言語拡張の一覧

Haskellのデファクトスタンダードな処理系であるGHCには，Haskellの言語仕様を補うような形で，GHC拡張と呼ばれる言語拡張を用意している．これらはちょっとした便利な糖衣構文を用意するようなものから型システムに深刻な影響を及ぼすもの，次期仕様策定までの前準備のものまで様々ある．いくつかの拡張はデフォルトで有効になっている．

言語拡張は，次の3つの方法で制御できる．

* すべての言語オプションは，コマンドラインフラグ`-X ... `（たとえば，`-XTemplateHaskell`）でオンになり、フラグ `-XNo ... `でオフになる．（たとえば，`-XNoTemplateHaskell`）
* GHCによって認識されている言語オプションは，**LANGUAGEプラグマ**(たとえば，`{-# LANGUAGE TemplateHaskell #-}`)を使用して有効にすることもできる．
* stack (hpack) を使っていれば，package.yamlのdefault-extensionで有効にすることもできる．[^1](パッケージごと)

[^1]: cabalも同様に{project名}.cabalのdefault-extensionで有効にできる．

以下は使用可能な言語拡張の一覧である．(GHC8.6.1[^2]に準拠)

[^2]: 喜べ，こいつは次のメジャーリリースだぞ

各言語拡張の詳しい説明，何が嬉しいか，どういうときに使われるかは随時別記事として追加していく．

## 拡張一覧

有効な拡張だけで締めて121個．多すぎ．

| 拡張 | 説明 |
|:-----|:----|
| AllowAmbiguousTypes | ユーザが曖昧な型を書くのを許し，型推論エンジンからそれらが推論されるようにする．|
| AlternativeLayoutRule | レイアウトルールを別のものに変更する |
| AlternativeLayoutRuleTransitional | AlternativeLayoutRuleのHaskell98向け |
| ApplicativeDo | Applivcative do-notationを脱糖衣できるようにする |
| Arrows | Arrow notationを有効にする |
| AutoDeriveTypeable | Typeable型クラスのインスタンスをderiving宣言がなくてもderivingする |
| BangPatterns | bang patternsを有効にする |
| BinaryLiterals | 2進数リテラルを使用可能にする |
| BlockArguments | do, case, if, let, mdo, procを関数適用する際に`()`を省略できるようにする[^3] |
| CApiFFI | CAPIの呼び出しを可能にする |
| ConstrainedClassMethods | 型クラスのメソッドに型制約を書けるようにする |
| ConstraintKinds | 制約種を有効にする |
| CPP | Cプリプロセッサを使えるようにする |
| DataKinds | データ型を昇格し種にできるようにする |
| DatatypeContexts | データ型の宣言に型クラス制約を書けるようにする |
| DefaultSignatures | 型クラスのメソッドの型シグネチャのデフォルトを提供できるようにする |
| DeriveAnyClass | 任意のクラスのderivingを可能にする |
| DeriveDataTypeable | Typeable型クラスのderivingを可能にする |
| DeriveFoldable | Foldable型クラスのderivingを可能にする |
| DeriveFunctor | Functor型クラスのderivingを可能にする |
| DeriveGeneric | Generic型クラスのderivingを可能にする |
| DeriveLift | Lift型クラスのderivingを可能にする |
| DeriveTraversable | Traversable型クラスのderivingを可能にする |
| DerivingStrategies | deriving戦略を指定できるようにする |
| DisambiguateRecordFields | レコードフィールドの曖昧さを許す |
| DoAndIfThenElse | do内でif-then-else式が書けるようになる．Haskell98向け　|
| DoRec | (非推奨) 再帰的なdo notationを許す．RecursiveDoに統合された |
| DuplicatedRecordFields | 同じ名前のフィールドを持つレコードの定義を許す | 
| EmptyCase | 空のCase式を許す |
| EmptyDataDecls | 空のデータ型の定義を許す |
| EmptyDataDeriving | 空のデータ型にderiving宣言を書けるようにする |
| ExistentialQuantification | 存在型の型シノニムを導入する |
| ExplicitForAll | 全称量化子の明示を可能にする |
| ExplicitNamespaces | キーワード`type`を用いて，importおよびexportのエントリの名前空間(値または型)を明示的に指定できるようにする |
| ExtendedDefaultRules | 通常のモジュールでGHCiの拡張デフォルト規則を使用できるようににする |
| ExtensibleRecords | 拡張可能レコードを使えるようにする |
| FlexibleContexts | 型クラス宣言において，型引数を複数持つ型クラス制約を書けるようにする |
| FlexibleInstances | インスタンス宣言において，型引数を複数持つ型クラス制約を書けるようにする |
| ForeignFunctionInterface | FFIを有効にする |
| FunctionalDependencies | 型クラス宣言において，関数従属を扱えるようにする |
| GADTs | 一般代数データ型を有効にする |
| GADTSyntax | GADTs風の記法使えるようにする |
| GeneralizedNewtypeDeriving | newtypeされた型のderivingを可能にする |
| Generics | 削除された |
| GHCForeignImportPrim | C--で書かれたGHCのプリミティブ演算をHaskellファイルにインポート可能にする |
| HexFloatLiterals | 16進数浮動小数点数リテラルを使用可能にする |
| ImplicitParams | 暗黙のパラメータを有効にする |
| ImplicitPrelude | Preludeを暗黙でインポートする |
| ImpredicativeTypes | 多相型を受け取れる多相型(Impredicative type)を使えるようにする|
| IncoherentInstances | Incoherentなインスタンスを有効にする[^4] |
| InstanceSigs | インスタンス宣言で型シグネチャを書けるようにする |
| InterruptibleFFI | 割り込み可能なFFIを有効にする |
| JavaScriptFFI | JavaScriptをFFIできるようにする |
| KindSignatures | Kindシグネチャを書けるようにする |
| LambdaCase | λ式チックにcase式を書けるようにする |
| LiberalTypeSynonyms | 型シノニムの宣言の制限を緩める |
| MagicHash | `#`を識別子の後置修飾子として許す |
| MonadComprehensions | モナド内包表記を使用可能にする |
| MonadFailDesugaring | doの脱糖衣においてMonadFailを使用する |
| MonoLocalBinds | ローカル束縛の一般化を禁止する |
| MonomorphismRestriction | 単相性制限を無効にする |
| MultiParamTypeClasses | 型クラス宣言において，型引数を複数取れるようにする |
| MultiWayIf | multi-way-if記法を有効にする |
| NamedFieldPuns | レコードのフィールド名に対する略記を使えるようにする |
| NamedWildCards | 型シグネチャでのワイルドカードの名前付けを許す |
| NegativeLiterals | 負数リテラルを有効にする |
| NewQualifiedOperators | 削除された |
| NondecreasingIndentation | do式のインデントルールを緩和する(Haskell98向け) |
| NPlusKPatterns | n+kパターンをサポートする |
| NullaryTypeClasses | 型引数なしの型クラス宣言を許す．MultiPramTypeClassesに統合された．|
| NumericUnderscores | `_`で数値リテラルを区切れるようにする[^3] |
| NumDecimals | 浮動小数点数リテラルの値が整数の場合に整数として扱う |
| OverlappingInstances | overlapping instancesを有効にする[^1] |
| OverloadedLabels | オーバーロードされたラベルを有効にする |
| OverloadedLists | オーバーロードされたリストを有効にする |
| OverloadedStrings | オーバーロードされた文字列リテラルを有効にする |
| PackageImports | パッケージを修飾付きインポートできるようにする |
| ParallelArrays | 並列処理向けの配列の構文をサポートする |
| ParallelListComp | リストの並行内包表記をできるようにする |
| PartialTypeSignatures | ワイルドカードを使った型シグネチャを許す |
| PArr | 削除された |
| PatternGuards | パターンガードを有効にする(デフォルトで有効) |
| PatternSignatures | (非推奨) 型シグネチャをパターンに書けるようにする．ScopedTypeVariablesに統合された |
| PatternSynonyms | パターンシノニムを有効にする |
| PolyKinds | Kind多相を使えるようにする |
| PostfixOperators | 後置演算子を使えるようにする |
| QuasiQuotes | Template HaskellにおけるQuasi-quotation記法を有効にする |
| Rank2Types | ランク２多相を使えるようにする |
| RankNTypes | 高階多相を使えるようにする |
| RebindableSyntax | 一部の構文を再束縛可能にする |
| RecordWildCards | レコードのワイルドカードを使用可能にする |
| RecursiveDo | 再帰的なdo notationを許す |
| RegularPatterns | リストに対して規則的なパターンマッチングを可能にする |
| RelaxedPolyRec | 多相な関数の相互再帰の制限を緩和する |
| RestrictedTypeSynonyms | 抽象データ型を実装する方法として一部の定義では透過的で，他の部分では不透明な型シノニムを扱えるようにする |
| RoleAnnotations | ロール注釈を有効にする |
| Safe | Safe HaskellをSafeモードにする |
| SafeImports | 削除された |
| ScopedTypeVariables | 字句スコープの型変数を許す |
| StandaloneDeriving | deriving宣言を単独で書けるようにする |
| StaticPointers | 閉じた式への参照を可能にするstatic構文を書けるようにする |
| Strict | 対象のモジュールの束縛をデフォルトで正格にする |
| StrictData | 対象のモジュールのデータ型をデフォルトで正格にする |
| TemplateHaskell | Template Haskellを有効にする |
| TemplateHaskellQuotes | Template Haskellのquotation記法を有効にする |
| TraditionalRecordSyntax | レコード記法を有効にする(デフォルトで有効) |
| TransformListComp | SQLチックな一般化されたリスト内包表記を有効にする |
| Trustworthy | Safe HaskellをTrustworthyモードにする |
| TupleSections | タプルのセクションを有効にする |
| TypeApplications | Type Application構文を使用可能にする |
| TypeFamilies | 型族を使用可能にする |
| TypeFamilyDependencies | 型族従属を使用可能にする[^5] |
| TypeInType | 明示的な種変数の量化，高階種, 種多相，種シノニム，種族などの機能を有効にし，型と同じように種を扱えるようにする |
| TypeOperators | 型演算子を使用可能にする |
| TypeSynonymInstances | インスタンスの型シノニムを使用可能にする |
| UnboxedSums | Unbox化された直和を使用可能にする |
| UnboxedTuples | Unbox化されたタプルを使用可能にする |
| UndecidableInstances | 決定不能な可能性もあるすべてのインスタンスを許す |
| UndecidableSuperClasses | 決定不能な可能性もあるすべての親クラス制約を許す |
| UnicodeSyntax | Unicode記法を使用可能にする |
| UnliftedFFITypes | 外部言語の型をUnbox化された型として使用可能にする |
| Unsafe | Safe HaskellをUnsafeモードにする |
| ViewPatterns | Viewパターンを有効にする |
| XmlSyntax | [Haskell Server Pages拡張言語](https://wiki.haskell.org/HSP)従って，具体的なXML構文を式とパターンで扱えるようにする |

[^3]: GHC8.6.1以降で利用可能
[^4]: この説明は説明になってないけども詳しい話は別記事でするよ(実際難しい)
[^5]: 今3秒で考えた訳なのでこういう訳だよってのがあれば教えてください

## `-fglasgow-exts`

`-fglasgow-exts`フラグを使用すると，以下の拡張が全て有効になる．(なお廃止予定)

* ConstrainedClassMethods
* DeriveDataTypeable
* DeriveFoldable
* DeriveFunctor
* DeriveGeneric
* DeriveTraversable
* EmptyDataDecls
* ExistentialQuantification
* FlexibleContexts
* FlexibleInstances
* ForeignFunctionInterface
* FunctionalDependencies
* GeneralizedNewtypeDeriving
* ImplicitParams
* KindSignatures
* LiberalTypeSynonyms
* MagicHash
* MultiParamTypeClasses
* ParallelListComp
* PatternGuards
* PostfixOperators
* RankNTypes
* RecursiveDo
* ScopedTypeVariables
* StandaloneDeriving
* TypeOperators
* TypeSynonymInstances
* UnboxedTuples
* UnicodeSyntax
* UnliftedFFITypes

# 分類

とりあえず適当に分類してみた．

**異議申し立て絶賛受付中**

## 記法の拡張，制限

* AlternativeLayoutRule
* AlternativeLayoutRuleTransitional (Haskell98)
* ApplicativeDo
* Arrows
* BlockArguments
* DoAndIfThenElse (Haskell98)
* DoRec (非推奨)
* EmptyCase
* EmptyDataDecls
* ExplicitNamespaces
* GADTSyntax
* LambdaCase
* MonadComprehensions
* MonadFailDesugaring
* MonoLocalBinds
* MultiWayIf
* NamedWildCards
* NondecreasingIndentation (Haskell98)
* ParallelListComp
* PartialTypeSignatures
* PostfixOperators
* QuasiQuotes
* RecursiveDo
* StandaloneDeriving
* StaticPointers
* TransformListComp
* TupleSections
* UnicodeSyntax
* XmlSyntax

## パターンマッチ

* NPlusKPatterns
* PatternGuards
* PatternSignatures (非推奨)
* PatternSynonyms
* RegularPatterns
* View Patterns

## リテラル

* BinaryLiterals
* HexFloatLiterals
* NegativeLiterals
* NumericUnderscores
* NumDecimals
* OverloadedStrings

## レコード

* DisambiguateRecordFields
* DuplicatedRecordFields
* ExtensibleRecords
* NamedFieldPuns
* OverloadedLabels
* RecordWildCards
* TraditionalRecordSyntax

## 制限の緩和

* AllowAmbiguousTypes
* GADTs
* ImplicitParams
* ImpredicativeTypes
* LiberalTypeSynonyms
* MonomorphismRestriction
* RebindableSyntax
* RelaxedPolyRec
* ScopedTypeVariables

## 型クラス

* ConstrainedClassMethods
* DatatypeContexts
* DefaultSignatures
* FlexibleContexts
* FlexibleInstances
* FunctionalDependencies
* IncoherentInstances
* InstanceSigs
* MultiParamTypeClasses
* NullaryTypeClasses
* OverlappingInstances
* TypeSynonymInstances
* UndecidableInstances
* UndecidableSuperClasses

## 量化

* ExistentialQuantification
* ExplicitForAll

## 種

* ConstraintKinds
* DataKinds
* KindSignatures
* PolyKinds
* Rank2Types
* RankNTypes
* TypeInType

## 型，型族

* ExplicitNamespaces
* TypeApplications
* TypeFamilies
* TypeFaimilyDependencies
* TypeOperators

## deriving可能な型クラス, データ型の拡張

* AutoDeriveTypeable
* DeriveAnyClass
* DeriveDataTypeable
* DeriveFoldable
* DeriveFunctor
* DeriveGeneric
* DeriveLift
* DeriveTraversable
* DerivingStrategies
* EmptyDataDeriving
* GeneralizedNewtypeDeriving

## Unbox

* MagicHash
* UnboxedSums
* UnboxedTuples

## Template Haskell

* TemplateHaskell
* TemplateHaskellQuotes

## FFI

* CApiFFI
* ForeignFunctionInterface
* InterruptibleFFI
* JavaScriptFFI
* UnliftedFFITypes

## Safe

* Safe
* Trustworthy
* Unsafe

## 正格

* BangPatterns
* Strict
* StrictData

## その他

* CPP
* ExtendedDefaultRules
* GHCForeignImportPrim
* ImplicitPrelude
* OverloadedLists
* PackageImports
* ParallelArrays
* RestrictedTypeSynonyms
* RoleAnnotations

# 参考文献

* [Glasgow Haskell Compiler User's Guide](https://downloads.haskell.org/~ghc/8.4.1/docs/html/users_guide/index.html#)
* [The Glasgow Haskell Compiler](https://www.haskell.org/ghc/)
* [Language.Haskell.Extension](https://www.haskell.org/cabal/release/latest/doc/API/Cabal/Language-Haskell-Extension.html)

不足や間違いなどあればコメントで指摘お願いします．

英語を読めない人，読みたくない人に捧ぐ