タプルはリストとは大きく異なります。リストでは、コンパイル時にサイズを知る必要はありませんが、タプルでは、コンパイル時に要素の数を知る必要があるだけでなく、各要素の型は他の要素から独立しています。
の型シグネチャを取得tl
:
- tl;
val it = fn : 'a list -> 'a list
つまり、 ofを取り、'a list -> 'a list
別のものを返します。タプル用も用意しないのはなぜですか? 次のようなものが欲しいと仮定しますtl
list
'a
y = (1,2,3);
tail y; (* returns (2,3) *)
なぜこれが意味をなさないのですか?の型シグネチャを考えてみてくださいtail
。それはどうなりますか?この場合、明らかに
'a * 'b * 'c -> 'b * 'c
'a
an 、 a 、a の積を取り、 a'b
と aの'c
積を返します。ML では、定義されたすべての関数に、静的に決定された型シグネチャが必要です。各タプル サイズは本質的に異なる型であるため、可能なすべてのタプル サイズを処理するタプル用の関数
を持つことは不可能です。'b
'c
tail
'a list
[1,2,3,4]
、または["A", "short", "sentence"]
、または [true、false、false、true、false] のように、多くの種類のリストの型になります。これらすべての場合において、型変数の値は'a
異なる型にバインドされます。(int、string、および bool)。また'a list
、任意のサイズのリストにすることができます。
しかし、タプルを取ります:
(1, true, "yes"); (* (int * bool * string) *)
("two", 2) (* (string, int) *)
("ok", "two", 2) (* (string, string, int) *)
リストとは異なり、これらはすべて異なるタイプです。したがって、すべてのリストの型シグネチャは単純ですが ( 'a list
)、すべてのタプルに「共通の型」はありません。2 タプルは 3 タプルとは異なる型です。
したがって、代わりにこれを行う必要があります。
y = (7, 8, 9);
(a, b, c) = y;
とa
は頭で、 で尻尾を再現できます(b,c)
。または、独自のテールを作成します。
fun tail (a,b,c) = (b, c)
これにより、そのような関数が意味をなさない理由についても直感的に理解できtail
ます。
fun tail (a,b) = (b)
| tail (a,b,c) = (b, c) (* won't compile *)
#
タプルの特定の要素を取得するために短縮形を使用することもできます。
#1 y; (* returns 7 *)
ただし、#1
これは関数ではなく、コンパイル時の省略形であることに注意してください。