(************************************************************ func.ml Created : Sat Jul 13 07:36:22 2002 Last modified: Fri Jul 19 13:43:01 2002 Compile: ocamlopt func.ml -o func # ************************************************************) (* interface *) module type StackSignature = functor (Element : sig type elt end) -> sig type elt = Element.elt type t (* abstract *) val empty : t val push : t -> elt -> t val pop : t -> (elt * t) end module type AbstractElementSignature = sig type elt val print : elt -> unit val increment : elt -> elt end (* implementation *) module StackImplementation : StackSignature = functor (Element : sig type elt end) -> struct type elt = Element.elt type t = elt list let empty = [] let push s e = e::s let pop s = match s with [] -> raise Not_found | top::remain -> (top,remain) end module StackManifest = StackImplementation( struct type elt = float end) (* StackImplementationをStackSignatureで制限しているおかげでstackの 実装がリストであることは見えない。 stackの要素がfloatであることは、StackManifest使用者から見える。 functorの実引数部分が struct type elt = float end : sig type elt = float end と型付けされるから *) module StackAbstract = StackImplementation( (struct type elt = int let increment e = e + 1 let print e = Printf.printf "%d!!\n" e end : AbstractElementSignature)) (* この場合も、 StackImplementationをStackSignatureで制限しているおかげでstackの 実装がリストであることは見えない。 stackの要素がintであることは、StackManifest使用者から見えない。 struct type elt = int end : sig type elt end と型付けされ、eltがabstractな型になるから *) (* まとめ。 functorの引数の部分はfunctor内でどんな名前の型、関数が必要かを示している だけであって、外からの(適用側からの)見え方を変えるわけではない。 仮引数の型は外からの見え方を変えるわけではない ↓ module F = functor (Arg : sig type t end) -> struct type s = Arg.t end module FManifest = F(struct type t = int end) module FAbstract = F((struct type t = int end : sig type t end)) Fの定義部分からは引数に"tという型が定義されている"ことさえわかればよい。 module FManifest : sig type s = int end 型が伝搬 module FAbstract : sig type s end (Structure : Signature) : Signature (制限のかかったstructureを返す)で制限 されている。つまり外からも見えないものを渡しているのだから。みえない。 (そしてなんの訳にも立たない..(というと怒られる?) FAbstractの型sへのアクセスが不可能だから) *)