これ:: a
は「任意のタイプ」を意味しますが、サブタイプではありません。、または、またはであるa
可能性がありますが、特にありません。正確には型ではなく、型変数です。Int
Bool
IO (Maybe Ordering)
a
次のような関数があるとします。
id x = x
コンパイラは、引数に特定の型がないことを理解していますx
。id から得られるものと同等である限り、任意の型をに使用できます。x
したがって、署名を次のように記述します。
-- /- Any type in...
-- | /- ...same type out.
-- V V
id :: a -> a
Haskell では、型は大文字で始まることに注意してください。これは型ではありません: 型変数です!
ポリモーフィズムを使用するのは、そのほうが簡単だからです。たとえば、コンポジションは便利なアイデアです。
(>>>) :: (a -> b) -> (b -> c) -> (a -> c)
(>>>) f g a = g (f a)
したがって、次のように書くことができます。
plusOneTimesFive :: Int -> Int
plusOneTimesFive = (+1) >>> (* 5)
reverseHead :: [Bool] -> Bool
reverseHead = reverse >>> head
しかし、すべての型を次のように書き出す必要があるとしたらどうでしょうか。
(>>>) :: (Bool -> Int) -> (Int -> String) -> (Bool -> String)
(>>>) f g a = g (f a)
(>>>') :: (Ordering -> Double) -> (Double -> IO ()) -> (Ordering -> IO ())
(>>>') f g a = g (f a)
(>>>'') :: (Int -> Int) -> (Int -> Bool) -> (Int -> Bool)
(>>>'') f g a = g (f a)
-- ...and so on.
それはばかげているでしょう。
したがって、コンパイラは次のように型の統合を使用して型を推測します。
これをGHCiに入力するとしましょう。ここでは簡単6
にするために で言いましょう。Int
id 6
コンパイラは次のように考えます: " 、そして、 , so , soid :: a -> a
が渡されます。Int
a = Int
id 6 :: Int
これはサブタイプではありません。サブタイプは型クラスを使用してキャプチャできますが、これは基本的なポリモーフィズムです。