変数名とスコープについてもっと意識する必要があります。
何が起こっているかというと、型コンストラクターa
と値コンストラクターを使用してデータ型を宣言したということですa
。次に、後でand関数a
の引数として使用します。これは、データ型のその値コンストラクターに一致していることを意味します。おそらくあなたが意図したものではありません。fst
snd
a
簡単な修正は、2 つの関数で使用される変数名を変更することです。
fun fst (x, y) = x;
fun snd (x, y) = y;
- fst(1,2);
val it = 1 : int
通常、問題はタイプから簡単に確認できますが、使用するのにかなり不幸な名前を選択したため、関数の元のタイプは
val fst = fn : a * 'a -> a
val snd = fn : a * 'a -> 'a
しかし、関数がデータ型 a を参照しないように修正されると、'a
代わりにa を持つことになります。
val fst = fn : 'a * 'b -> 'a
val snd = fn : 'a * 'b -> 'b
一般に、値コンストラクターの場合は大文字で開始し、型コンストラクターの場合はすべて小文字で開始するのが良いスタイルと考えられています。1 つの例はオプションのデータ型ですが、値のコンストラクターにはすべて大文字を使用します (これを強制する他の言語もあります)。
datatype 'a option = NONE
| SOME of 'a
型と値に使用される名前を分離し、それを「最初の」ポリモーフィック型変数の一部としても使用されるため、「a」以外の名前で呼ぶと、全体の考え方がより理にかなっている可能性があります (つまり、ほとんどのインタープリターは'a
)。
datatype foo = Bar;
val x = Bar;
val y:foo = Bar;
val z = Bar;
fun fa Bar = Bar;