値制限

なんかTLで偶然そんな話題があったので。 コードはF#です。

まずrefについて

値制限の話題に行く前に、refについて説明します。 refは、「変更可能な値」を実現するために使える型で、大体こんな感じに実装されています。

type 'a ref = { mutable contents: 'a }
(* refの生成 *)
let ref x = { contents = x }
(* refが格納している値を参照 *)
let (!) x = x.contents
(* refが格納している値に再代入 *)
let (:=) x y = x.contents <- y

これによって、以下のようなコードが書けます。

let a = ref "hoge"
printfn "%A" !a

a := "piyo"
printfn "%A" !a

これを実行すると、hogeとpiyoが出力されます。 aの指す値が途中で変わっているということですね。

では、こんなコードは許されるでしょうか?

let xs = ref []

これが許されるとするならば、xsの型は'a list refとなるでしょう。 ではさらにコードを追加してみましょう。

(* xsの型が'a list refとするならば・・・ *)
let xs = ref []

let f (ints: int list) =
  (* xsは'a list refなんだから、これは合法 *)
  xs := ints

let g (strs: string list) =
  (* xsは'a list refなんだから、これは合法 *)
  xs := strs

あるぇー?fを実行したらxsの中にはint listが、次にgを実行したらxsの中にはstring listが入っていることになってしまう! 静的な型とはいったい何だったのか・・・

値制限とは

と言うことで、この問題を回避するために値制限と言うものがあります。 要は、

let xs = ref []

を自動ジェネリック化しない、ということですね。

(書きかけ。あとで何か書くかも?)