値制限
なんか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 []
を自動ジェネリック化しない、ということですね。
(書きかけ。あとで何か書くかも?)