Semantics of Includes

Includes can be used inside of structures and inside of signatures. Of course, when we include inside a signature, we must be including another signature. And when we include inside a structure, we must be including another structure.

Including a Structure

Including a structure is like writing a local definition for each name defined in the module. Writing include ListSetDups as we did above, for example, has an effect similar to writing exactly the following:

module ListSetDupsExtended = struct
  (* BEGIN all the includes *)
  type 'a t = 'a ListSetDups.t
  let empty = ListSetDups.empty
  let mem   = ListSetDups.mem
  let add   = ListSetDups.add
  let elts  = ListSetDups.elts
  (* END all the includes *)
  let of_list lst = List.fold_right add lst empty
end

But if the set of names defined inside ListSetDups ever changed, the include would reflect that change, whereas the static code we wrote above would not.

Including a Signature

Signatures also support includes. For example, we could write:

module type SetExtended = sig
  include Set
  val of_list : 'a list -> 'a t
end

Which would have an effect similar to writing the following:

module type SetExtended = sig
  (* BEGIN all the includes *)
  type 'a t
  val empty : 'a t
  val mem   : 'a -> 'a t -> bool
  val add   : 'a -> 'a t -> 'a t
  val elts  : 'a t -> 'a list
  (* END all the includes *)
  val of_list : 'a list -> 'a t
end

And that module type would be suitable for ListSetDupsExtended:

module ListSetDupsExtended : SetExtended = struct
  include ListSetDupsImpl
  let of_list lst = lst 
end

By sealing the module, we've again made 'a t abstract, so no one outside that module gets to know that its representation type is actually 'a list.

results matching ""

    No results matching ""