let build_sloq n =
let rec qbuild i q = if i=0 then q
else qbuild (i-1) (Queue.enqueue q i)
in qbuild n Queue.empty_q
let rec empty_sloq q = if Queue.is_empty q then ()
else let q' = Queue.dequeue q in
empty_sloq q'
let build_fq n =
let rec qbuild i q = if i=0 then q
else qbuild (i-1) (FastQ.enqueue q i)
in qbuild FastQ.empty_q
let rec empty_fq q = if FastQ.is_empty q then ()
else let q' = FastQ.dequeue q in
empty_fq q'
This looks like an opportunity for code reuse…
A functor is a module that acts on one or more other modules as arguments:
Module typing is “structural”:
module SlackerQ = struct
type 'a q = Nevs of 'a | Whatevs
let empty_q = Whatevs
let is_empty q = true
let enqueue q x = Whatevs
exception OMG
let peek q = raise OMG
let dequeue q = Whatevs
exception EmptyQ = OMG
end
Module M
matches signature S
if it has the minimal functionality (matching names, types) required by S
.
Signatures and Structures can be anonymous…
But they are not “first-class” types and values:
Functors offer another approach to polymorphism:
module type OrdSig = sig
type t
val compare : t -> t -> int
end
module BSTree (Item : OrdSig) =
struct
type elt = Item.t
type t = Empty | Node of elt*t*t
let empty = Empty
let rec search t x = (* some stuff *)
let rec insert t x = (* more stuff *)
let rec fold f acc t = (* you know *)
end
module StringBST = BSTree(String)
Suppose we want to make the BSTree.t
type abstract…
Problem: BST.elt
is abstract. It can be “opened” with a sharing constraint:
module BSTree (Item : ordered) : BST
with type elt = Item.t =
struct
(* all that stuff a third time *)
end
How would we use the BSTree functor to make a case-insensitive BSTree?
OCaml’s Set.Make
, Map.Make
functors work similarly…
cs2041.org