I’m trying to create a functor with a sort of polymorphic default
argument, but having no luck.
Here’s the failed idea:
First, a module with a pretty printer for a container element:
module type PP =
sig
type t
val pp : t Fmt.t
end
And then the most general functor for an ordered container:
module Make2 (Pp : PP) (Ord : Set.OrderedType with type t = Pp.t) =
struct
type elt = Pp.t
type t =
| Empty
| Tree of elt * int * t * t
(* ... *)
end
Now the polymorphic “default” argument for Pp in Make2:
module Default_pp =
struct
type 'a t (* XXX *)
let pp ppf _ = Fmt.string ppf "<element>"
end
And the simpler functor providing convenience over configurability:
module Make = Make2(Default_pp)
… used like:
module IntOrd = struct type t = int let compare = Int.compare end
module IntM = Make(IntOrd)
module FloatOrd = struct type t = float let compare = Float.compare end
module FloatM = Make(FloatOrd)
But the Make2 application has the error:
Modules do not match:
sig type 'a t = 'a Default_pp.t val pp : Format.formatter -> 'a -> unit end
is not included in PP
Type declarations do not match:
type 'a t = 'a Default_pp.t
is not included in
type t
I realize the extra 'a parameter is the problem, but I don’t know how
to specify the correct polymorphic type. I’m assuming I need a
polymorphic type here for it to serve as a “default”, but maybe
there’s an alternative using type constraints in the signature of Make
or Make2.
How could this be done, either along the above lines, or in some other
completely different way?
I hope someone can help. Thanks,