小ネタ集

いろいろ思いつく訳です。

recursive module

module rec M : sig f : unit -> unit end = M
let _ = M.f

こりゃ一体どういうことなんでしょうね。

これに関連して、camlinternalMod.ml の ignore pad1 から ignore pad8 までがとっても気になります。

binary operator with optional arguments

let (+) ?(x=0) y z = x + y + z
let _ = 1 + 2
let _ = (+) ~x:3 1 2

何かの役に立ちそうです。ただし、(1 + 2) ~x:3 は出来ません。

private alias がやっぱりイマイチ使えない

module M : sig
  type 'a t = private 'a
  val pack : 'a -> 'a t
end = struct
  type 'a t = 'a
  let pack x = x
end

let l = []
let packed_l = M.pack l

pack は関数なので、polymorphic な値を pack しても monomorphic になってしまいます。

  • pack する対象(l) は M の外に置きたい。
  • eta conversion したくない。つうか、上の例だと出来ない。

なので詰んでしまいました。

Obj.magic が関数なのは困る。

上の続き。邪道ですが、pack じゃなくて、Obj.magic を使ってみました。

let packed_l : 'a list M.t = Obj.magic l

これでもダメです。Obj.magic もやっぱ関数なので、無理矢理型は変えられますが、expansiveness は変えられない。

  • 関数じゃないプリミティブの Obj.magic
  • private を一時的に無視できるような仕組み (オレオレ friend モジュール?)
  • private っぽいけど一方通行じゃなくて、明示的 coercion を使えば行き来できるような abbreviate type: (t :> s), (s :> t) が出来るけど t と s は unifiable ではない。

のうちどれかが欲しいなぁ。最後のが格好よさそうだ。