目に見える型適用
TypeApplications
8.0.1以降
型適用構文を使用できるようにする.
TypeApplications拡張を使用すると,式の中で目に見える型適用を使うことができる.例:show (read @Int "5").@Intは目に見える型適用である.それはreadの型の型変数の値を指定する.
目に見える型適用の前には@記号が付く(構文を明確にするために,@の前に識別子を構成しない文字(通常はスペース)を入れる必要がある.たとえば, read@Int 5は解析されない).関数の完全な多相型がわかっているときはいつでも使用できる.関数が識別子である場合(一般的なケース),その型は,識別子に型シグネチャが与えられている場合にのみ既知と見なされる.識別子が型シグネチャを持たない場合,目に見える型適用は使用できない.
詳細は以下のとおりである.
識別子の型シグネチャに明示的なforallが含まれていない場合は,型変数の引数は,変数が型に現れる順番に左から右の順に現れる.したがって,foo :: Monad m => a b -> m (a c)は,型変数がm, a,b,cの順に並べられる.
いずれかの変数が他の変数に依存している場合(つまり,一部の変数が種変数の場合),種変数が型変数の前に来るように変数が並べ替えられ,左から右への順序ができる限り維持される.つまり,GHCは変数に対して安定したトポロジカルソートを実行する.
例えば,bar :: Proxy (a :: (j, k)) -> bの場合は,その変数はj、k、a、bのように並べられる.
目に見える型適用はユーザ定義の型変数のみをインスタンス化するために使用できる.つまり,data Proxy a = Proxyでは,aの種で使われている言及されていない種変数は目に見える型適用では使用できない.
型クラスのメソッドの型引数は,型クラスの型変数が含まれ,その後に各メソッドの多相性を持つ変数が続く.したがって,class Monad m where return :: a -> m aは,returnの型引数がm, aであることを示す.
RankNTypes拡張(字句的スコープを持つ型変数(訳注:おそらくこのリンクはミス.本当は任意ランクの多相だと思われる))を使えば,型の先頭以外の場所で型引数を宣言することが可能である.たとえば,pair :: forall a. a -> forall b. b -> (a, b) の場合,pair @Bool True @Charと書くことができて,それはChar -> (Bool, Char)型を持つことになる。 部分型シグネチャ(部分型シグネチャ)は目に見える型適用でうまく機能する.2番目の型引数のみをwurbleに指定したい場合は ,wurble @_ @Intと書けば良い.最初の引数はワイルドカードで,部分型シグネチャと同じである.ただし,目に見える型適用で使用する場合は,PartialTypeSignaturesを指定する必要はなく,コードでは省かれた型を知らせる警告が生成されることはない. -fprint-explicit-forallsによる型のプリントが有効な場合,目に見える型適用が行えない型変数は中括弧の中に入った形でプリントされる.GHCiセッションでこの振る舞いを観察することができる.
code: vta1
:set -XTypeApplications -fprint-explicit-foralls
let myLength1 :: Foldable f => f a -> Int; myLength1 = length
:type +v myLength1
myLength1 :: forall (f :: * -> *) a. Foldable f => f a -> Int
let myLength2 = length
:type +v myLength2
myLength2 :: forall {a} {t :: * -> *}. Foldable t => t a -> Int
:type +v myLength2 @[]
<interactive>:1:1: error:
• Cannot apply expression of type ‘t0 a0 -> Int’
to a visible type argument ‘[]’
• In the expression: myLength2 @[]
myLength1は明示的な型シグネチャを伴って定義されているので、 :type +vはその型変数のすべてが型適用できるということを報告することに注意せよ.一方,myLength2には型シグネチャが与えられていない.その結果,その型変数はすべて中括弧で囲まれ,myLength2で目に見える型適用を使用しようとしても失敗する.
また,:typeの代わりに,:type +vを上記のGHCiセッションで使用したことに注意せよ.これは,:typeは与えられた式に割り当てられた変数に対して推論した型を表示するからである.(つまり,let x = <expr>におけるxの型).myLength2を使用して上記で説明したように,この型には目に見える型適用で使用できる変数はない.一方,:type +vは与えられた式の実際の型を表示する.このことを例証すると,
code:vta2
:type myLength1
myLength1 :: forall {a} {f :: * -> *}. Foldable f => f a -> Int
:type myLength2
myLength2 :: forall {a} {t :: * -> *}. Foldable t => t a -> Int
:typeを使用すると,myLength1の型シグネチャの型変数は型適用に使用できないという(訳注:誤った)結論をユーザーに抱かせうる.しかし,これは正しくない. 目に見える型適用のプロパティに関して最も正確な情報が必要な場合は,必ず:type +vを使用すること.