多相性と書き換え可能データ

let で名前の付けられる式が値でない場合,多相性に制約がつくことがある。値でないとはたとえば参照などだ。

# let x = ref [];;
val x : '_a list ref = {contents = []}

x は参照で,中身は空のリストだ。空だから何のリストでもいい(多相)はずで,型も ‘_a となっている。ここで1をコンスしてみる。

# 1 :: !x;;
- : int list = [1]

当然うまくいく。x 自身を書き換えたわけではないので,まだ中身はカラリストのままだ。じゃ,今度は ‘a’ をコンスしてみると:

# 'a' :: !x;;
Characters 7-9:
'a' :: !x;;
^^
This expression has type int list but is here used with type char list

エラーになった。int のリストじゃないといけないといってる。あわてて x の型を確認してみると:

# x;;
- : int list ref = {contents = []}

int list への参照に変わってしまっている。

どういう訳なのか理解できないのだけど,はじめ多相的だったものが,いったん int list として評価されたことで型が確定してしまった,ということだろうか。少なくとも現象としてはそういうことらしい。

ちなみに,参照ではなくただの空リストなら問題ない。

# let y = [];;
val y : 'a list = []
# 1 :: y;;
- : int list = [1]
# 'a' :: y;;
- : char list = ['a']