Commits

camlspotter committed 6349a58

space

Comments (0)

Files changed (1)

module_coercion.md

 
 OCaml では module を tuple と同じブロック構造に変換する:
 
+
     $ ocaml -dlambda
 	...
 	# module M = struct let x = 42 let y = "hello" end;;
       (let (x/1021 42 y/1022 "hello") (makeblock 0 x/1021 y/1022)))
     module M : sig val x : int val y : string end
 
+
 `(makeblock 0 x/1021 y/1022)` というのがその部分。 Tuple でも同じ:
 
+
     # (fun x y -> (x,y)) (42, "hello");;
     (after //toplevel//(1):0-32
       (apply
         [0: 42 "hello"]))
     - : '_a -> (int * string) * '_a = <fun>
 
+
 `(x,y)` の部分が `(makeblock 0 x/1021 y/1022)` になっている。
 
 なので `sig val x : int val y : string end` のモジュールは `int * string` と
 `(int * string)` という型の tuple があったとして、それを `(string * int)` という
 型に使えるかというともちろんそんなことはできない。
 
+
     # (Obj.magic (42, "hello") : (string * int));;
     Segmentation fault (core dumped)
-	
+
+
 が、ML のモジュールは? `sig val x : int val y : string end` という型を持つ
 モジュールは `sig val y : string val x : int end` という型にしても良い。
 
+
     # module M = struct let x = 42 let y = "hello" end;;
     module M : sig val x : int val y : string end
     # module N = (M : sig val y : string val x : int end);;
     module N : sig val y : string val x : int end
-	
+
+
 あれ? Tuple ではクラッシュするのになぜ module ではクラッシュしない?
 `sig val x : int val y : string end` の型を持つモジュールは `(int * string)` 
 と同じ構造をしているはず、 `sig val y : string val x : int end` の型にすると
 もしコンパイラが何も特にしていなかったとすれば、 tuple の例と同じでクラッシュするはずだ。
 クラッシュしないということは何か特別なことをしているから。
 
+
     $ ocaml -dlambda
 	...
     # module M = struct let x = 42 let y = "hello" end;;
         (makeblock 0 (field 1 M/1020) (field 0 M/1020))))
     module N : sig val y : string val x : int end
 
+
 単に `N` は `M` と同じ値ではなく変換が入っている。
 `(makeblock 0 (field 1 M/1020) (field 0 M/1020))` の部分。
 `M` の 1番目を 0番目に、0番目を 1番目に置いたブロックを作っている。