今日は夏に向けていっちょOCaml界に伝わる怪談話でも…
ではなくて、幽霊型について。
使えたら面白そうだと思うのですが正直未だに実践で使ったことがないので、非常に残念な気分になりつつも書いていきます。
幽霊型は次のように定義できます。
# type 'a number = int;; type 'a number = int
numberという謎の型名が出てきましたが、これでも型が定義できます。これを幽霊型と言います。
type 'a <任意の名前> = <既存の型>
のように書くことで、定義できると思ってください。(自分、詳細知らないんで(ぉ )
おそらくちょっと変わった使い道としてはconstraint(型強制)とpolymorphic variant(多相ヴァリアント)との組み合わせ(よく知らんけど。ほかに使い道あるかもしれんけど。多相ヴァリアントなしの基本的な場合は記事最後の追記を参照)。例えば同じ文字列同士でも持っている意味が異なっているようなデータとして、プログラムのコードとプレーンテキストがあります。これをちゃんと型として区別して扱いたいというときに幽霊型で解決してみましょう。
module Text : sig type 'a text constraint 'a = [< `Plain | `Code ] (** 二つのテキストを生成 *) val make_plain : string -> [`Plain] text val make_code : string -> [`Code] text (** どちらもプレーンテキストとして読むことができる *) val output_plain : 'a text -> unit (** プログラムとして読み込めるのはコードのみ *) val exec_code : [`Code] text -> unit end = struct type 'a text = string constraint 'a = [< `Plain | `Code ] let make_plain x = x let make_code x = (** 正しいコードか解析したあとにその文字列を返す; 試しなら x でおk *) let output_plain = print_endline let exec_code s = (** ここでコード実行 ; 試しに動かすときは print_endline "exec!" とでも *) end
のようにすることができます。では使ったときにどうなるか見てみましょう。
# open Text;; # let p = make_plain "aiueo" ;; val p : [ `Plain ] Text.text = <abstr> # let c = make_code "open Int32" ;; val c : [ `Code ] Text.text = <abstr> # exec_code p ;; Error: This expression has type [ `Plain ] Text.text but an expression was expected of type [ `Code ] Text.text These two variant types have no intersection # exec_code c ;; - : unit = () # output_plain p ;; aiueo - : unit = () # output_plain c ;; open Int32 - : unit = ()
上のようになります。
特に気になるのは exec_code が [`Plain] text をはじいていることと、print_endline を output_plain で用いながらも、ちゃんと動作していることです。つまり、型としては 'a text は string として渡すことができ、しかも [`Code] text と [`Plain] text の型はちゃんと判断できる。型の恩恵丸出し、セキュリティアップな感じです。多分データベース込みのWebアプリとかのデータのやり取りで型の恩恵を受けることも可能ですよね。夢は広がる、が今のところ目下の自分の使い道は無し。。。
追記:
Twitterでリプライもらいました。ありがとうございます。
@Naoki_Rin 基本的な phantom は poly variant は必要ないよ。型間のサブタイピングが欲しいときだけに必要になります。簡単な例はこれとかが良いでしょう URL
2012-05-03 18:39:26 via TweetDeck to @Naoki_Rin
なんか変なこと言ってた。。。普通のはいつも使ってるっての。type 'a t = 'a listとか書くくせに。頭がヤバい…