2011-12-15 6 views
11

インタラクティブGHCインタプリタを使用している場合、表現の推論されたタイプに依頼することが可能です:GHCiは型変数の名前をどのように選ぶのですか?

Prelude> :t map 
map :: (a -> b) -> [a] -> [b] 

mapdefined

として あるので、それは署名から型変数の名前を取るようですプレリュードの
map :: (a -> b) -> [a] -> [b] 
map _ []  = [] 
map f (x:xs) = f x : map f xs 

それはたくさんの意味があります!私の質問は:どのように署名が与えられていないときに型変数名を選んだのですか?

の例では、それは名前bb1を選ん

Prelude> :t map fst 
map fst :: [(b, b1)] -> [b] 

だろう。これは、名前の変更が行われなければならないことは明らかだが、単純に、...私は少し読みやすく見つける代わりに

map fst :: [(a, b)] -> [a] 

、与えられただろうab始まります。

答えて

13

私が理解するように、ghciは、タイプを推論するのと同じ順序で名前を選択します。これは、結果の型名を決定するために前述の命名スキームを使用します。[b]は、mapの定義で指定された型名であるためです。次に、mapの最初のパラメータである関数がb型のものを返す必要があると判断します。

したがって、残りの型変数は、引数タプルの2番目の要素の型変数fstになります。また、fstの定義を参照して、使用する名前を決定します。 fst :: (a, b) -> aの定義はbとなりますが、既にbが使用されているので、1が付加されてb1になります。

このシステムは、ここでのように任意のタイプを扱わない状況では利点があると思います。結果の型は次のようになります場合は、例えば:あなたはほとんどそのn#に頼ることができるので、数値を意味...

castAdd :: (Num a, Num b, Num c) => a -> b -> c 

castAdd :: (Num n, Num n1, Num n2) => n -> n1 -> n2 

...それは間違いなく、より読みやすい未満でありますtypeはNumのクラス定義がclass Num n where ...であるためです。

編集:はい、私はcastAddを実装することは不可能ですが、単なる型の例です。

+1

ありがとう、それは良い説明です!私はいくつかの「n」の名前を変更したいが、関連したままにしたい場合は考えなかった。 –

+0

それは不可能ではありません。 (unSafeCoerceか普通の古い '_ | _') – PyRulez

関連する問題