4

のような関数が与えられると、negate次の型シグネチャがあります。

negate :: Num a => a -> a

これaは、コンテキスト内のタイプであると説明しNumます(私が間違っていると思われる場合は修正してください)。

lastしかし、型シグネチャを持つ のようなものを記述する方法が完全にはわかりません。

last :: [a] -> a

私の推測では、それはタイプ固有ではなく、リストを取り、リストと同じタイプの単一の値を生成します。これはそれについて考える正しい方法ですか?

4

3 に答える 3

5

まず、はのコンテキストの型でなくa、インスタンスを持つ型です。NumNum

Num a => a -> a制約付きポリモーフィック タイプですが、[a] -> aは制約なしポリモーフィック タイプ、または略して単なるポリモーフィック タイプです。制約のない場合、a任意の型にすることができます。制約付きの場合、指定された制約に従う型でなければなりません。

于 2021-02-08T15:24:36.283 に答える
0

last :: [a] -> aSystem 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インスタンスを持つものに対してのみ機能します (両方とも機能IntDoubleますが、 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’
于 2021-02-09T13:34:44.357 に答える