let多相には色々と種類があるので、ちと注意が必要です。
参照型と型安全を両立させるため、let多相を値に制限する方法。 TAPLでも紹介されています。値制限は、かなーり厳しい。
# let fst (x, _) = x;; val fst : 'a * 'b -> 'a = <fun> # let v = fst ([], ());; val v : '_a list = [] #
fst ([], ()) は値ではなく、関数適用なので、多相にはならない。
OCamlのlet多相には基本的に値制限が付いています。 ただし、型変数がcovariantな位置に現れる場合は、subtype関係から多相が回復します。
# let fst (x, _) = x;; val fst : 'a * 'b -> 'a = <fun> # let v = fst ([], ());; val v : 'a list = [] #
covariantな位置というのは、(不正確ですが)関数の型を表す→の右側と思ってください。 つまり例えば、関数の戻り値に型変数があるなら、それはcovariantな位置の型変数です。 正確には圏論的に言うと(以下略
大堀先生が考案され、SML# に実装されている方法です。