last :: [a] -> a
System F型の Haskell98 構文です。
last :: ∀ a. [a] -> a
これ∀ a
は一種の型レベル ラムダ バインディングとして理解できます。つまり、実際の値レベル リスト パラメータの前に、関数はリストに含まれる要素の型を示す型レベル引数を受け取ります。この普遍的な量化により、関数はパラメトリックに多態的になります。
通常、型変数は型チェッカーによって自動的に挿入されます。新しいGHC Haskellでは、それらを明示的に適用することもできます:
Prelude> :set -XTypeApplications
Prelude> :t last @Int
last @Int :: [Int] -> Int
Prelude> last @Double [5,6,7]
7.0
negate
もパラメトリックにポリモーフィックですが、last
それとは異なり、「すべての」タイプに対して真に機能するのではなく、Num
インスタンスを持つものに対してのみ機能します (両方とも機能Int
しDouble
ますが、 eg は機能しませんChar
)。つまり、型を指定する追加の引数だけでなく、実際にインスタンスがあることの証明も受け入れます。Num
それもコンパイラによって自動的に挿入されます。
negate :: ∀ a. Num a => a -> a
Prelude> :t negate @Int
negate @Int :: Int -> Int
Prelude> :t negate @Char
<interactive>:1:1: error:
No instance for (Num Char) arising from a use of ‘negate’