読者です 読者をやめる 読者になる 読者になる

私の貧弱なOCaml力を晒す 第五回 「OCamlの怪」

今日は夏に向けていっちょ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でリプライもらいました。ありがとうございます。

なんか変なこと言ってた。。。普通のはいつも使ってるっての。type 'a t = 'a listとか書くくせに。頭がヤバい…

広告を非表示にする