7.12. Constraintという種

通常、制約(型の中で=>の左に出現するもの)の構文は極めて強く制限されている。次のものにしかなれない。

-XConstraintKindsフラグを使うと、これより広い範囲ものを制約として受け付けるようになる。正確にいうと、このフラグのもとでは新しい種Constraintを持つあらゆるを制約として使える。以下のものが種Constraintを持つ。

制約は特定の種を持った単なる型として扱われるので、この拡張によって制約シノニムが可能になる。

type Stringy a = (Read a, Show a)
foo :: Stringy a => a -> (String, String -> a)
foo x = (show x, read)

現在、標準的な制約およびタプルと、これら二種類の制約を基にしたシノニムのみが、インスタンス文脈とスーパークラス文脈で(別のフラグなしで)使用できる。この理由は、もっと一般的な制約を許すと型検査のループを引き起し得るからである。以下の二つのプログラムはそのような例である。

type family Clsish u a
type instance Clsish () a = Cls a
class Clsish () a => Cls a where
class OkCls a where

type family OkClsish u a
type instance OkClsish () a = OkCls a
instance OkClsish () a => OkCls a where

インスタンス文脈やスーパークラスに変わった種類の制約を使うプログラムを書くことはできるが、それには-XUndecidableInstancesを使って、型検査器が終了しなくても気にしないことを示す必要がある。