メモ
OCaml 3.12での話なんですが
(* is_empty_ Map.Make(String) something is_empty_ Map.Make(Int32) something *) let is_empty_ modl = let module Modl = (val modl : Map.S) in let aux (map : 'a Modl.t) = Modl.is_empty map in aux (* local module 'Modl' try escape to global! *)
しょうがないからlet module Modl = ...としていて、本質的にはmodlと同じ筈なのに、ところがmodlと書けないからModlと書くとローカルなモジュールが逃亡をはかろうとしていると言われて、
まぁローカルモジュールが逃げようとしていて怒られるのは良いとして、いや・・・そういうことじゃないんです・・・って感じになっていて、
どうすれば良いんでしょう。
出来ると嬉しいかもしれない
let is_empty_ (type x) modl = let module Modl = (val modl : Map.S with type ('a t) = x) in let aux (map : x) = Modl.is_empty map in aux
いや...しかしコレは...
一応
http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html
を見ると
With first-class modules, it is possible to parametrize some code over the implementation of a module without using a functor. let sort (type s) set l = let module Set = (val set : Set.S with type elt = s) in Set.elements (List.fold_right Set.add l Set.empty) The type inferred for this function is (module Set.S with type elt = ’a) -> ’a list -> ’a list.
とすればローカルからのモジュール脱出は防げると書いてるんですよね。
メモメモ
ゴミバージョン
let is_empty_ (type x) modl map = let module Modl = (val modl : Map.S) in let (map_ : x Modl.t) = Obj.magic map in Modl.is_empty map_
このis_empty_の型は
type: (module Map.S) -> 'a -> bool
となっていてゴミ使えないですよ…。