ボクがObj.magicを使うシチュエーション

要約

  • とりあえずコンパイルを通したいときは、Obj.magicを使うと便利だよ
  • でも、Obj.magicを使ったコードを公開したり、レポジトリにコミットしたらダメだよ

Obj.magicがないと困るとき

シグネチャ付きのモジュールを書くとき、先にシグネチャを書いたりしますよね。

module M : sig
  val f : int -> int
  val g : char -> char
end = struct
end

で、fから順に実装していきます。

module M : sig
  val f : int -> int
  val g : char -> char
end = struct
  let f n = n + 1
end

で、この段階でfに型エラーがないか確かめるために、コンパイルしたくてもできません。

$ ocamlc foo.ml
File "foo.ml", line 4, characters 6-33:
Error: Signature mismatch:
       Modules do not match:
         sig val f : int -> int end
       is not included in
         sig val f : int -> int val g : char -> char end
       The field `g' is required but not provided

そこで...

Obj.magicの出番です。

まず、Obj.magicを使って'a型の変数を作ります。

(* val undef : 'a = <poly> *)
let undef = Obj.magic 42

で、これを使って、gを実装します。

let undef = Obj.magic 42

module M : sig
  val f : int -> int
  val g : char -> char
end = struct
  let f n = n + 1
  (* gに適当な実装を与える *)
  let g = undef
end

これで、コンパイルできるようになります。やったね。

$ ocamlc foo.ml
$

注意

でも、undefが入ったままのコードを公開したり、レポジトリにコミットしたらダメだよ。