generated at
非可述多相

ImpredicativeTypes
RankNTypes を含む.
6.10.1以降.
非可述多相型を許す.

一般的に, GHCは多相な関数を単相型( forall のないようなもの)でのみインスタンス化する. 例えば,

ip01.hs
runST :: (forall s. ST s a) -> a id :: forall b. b -> b foo = id runST -- Rejected

foo の定義においては, id の型を b := (forall s. ST s a) -> a に具体化するしかないが,それが許されないため foo の定義は拒否される.多相な型に具体化される多相な型変数は非可述多相と呼ばれる.

GHCの非可述多相( ImpredicativeTypes 拡張によって有効化される)のサポートは極めて信用ならない.この拡張がうまく動けば, 多相型で多相的な関数を呼び,多相型上でデータ構造をパラメータ化することだってできることを意味するだろう.例えば,

ip02.hs
f :: Maybe (forall a. [a] -> [a]) -> Maybe ([Int], [Char]) f (Just g) = Just (g [3], g "hello") f Nothing = Nothing

ここで, Maybe 型は多相型 (forall a. [a] -> [a]) によってパラメータ化されていることに注意すること.

しかしながらこの拡張はとても実験的な機能であると考えられるべきであり,確実にサポートされなくなるべきである.試してもらうのは大いに結構だが,ずっと動いてくれることや今後のリリースで同じ挙動を保ち続けてくれることを当てにするのはお願いだからしないでいただきたい.詳しくはこのwikiのページを参照のこと.

非可述多相を使いたい場合,主なワークアラウンドとしてはnewtypeラッパーを用いるという手がある.前述の id runST の例は,このワークアラウンドを使って次のように書くことができる.

ip03.hs
runST :: (forall s. ST s a) -> a id :: forall b. b -> b newtype Wrap a = Wrap { unWrap :: (forall s. ST s a) -> a } foo :: (forall s. ST s a) -> a foo = unWrap (id (Wrap runST)) -- Here id is called at monomorphic type (Wrap a)