module Generic_core_extensible:sig
..end
Type-indexed functions are ad-hoc polymorphic functions rather than parametric polymorphic: their behaviour may change depending on the type.
We implement them in Ocaml using a type 'a ty
(see Generic_core_ty.ty
) whose
constructors reflect the type parameter:
Int : int ty
List : 'a ty -> 'a list ty
The type ty
is extensible to allow users to add their own types.
Therefore when defining functions on ty
we need to be able
to extend them as we extend ty
. This is the purpose of this
module.
The general type of type-indexed function is given by
type 'f ty_fun = { f : 'a . 'a ty -> ('a,'f) app }
where we used a defunctionalisation method to deal with
parameterised types, see Generic_util_app
. The
idea is that ('a, 'f) app
represents the application of a
type 'f
to a type parameter 'a
.
An extensible function is a collection of such ty_fun
.
A collection is created with function create
whose result is a closure
of type 'b extensible_closure
whose field f
is the extensible function,
and field ext
allows to extend it to a new case by providing
a type pattern and a ty_fun
matching that type pattern.
Calling the extensible function with the field f
will raise
a Type_pattern_match_failure
exception when the type index
doesn't match any of the patterns in the collection.
Extending an extensible function with the field ext
will
raise a Type_pattern_overwrite
exception when called with
a type pattern that was already registered.
exception Type_pattern_match_failure of string
f
field of a Generic_core_extensible.closure
when there is no
case registered to deal with the type witness.exception Type_pattern_overwrite of string
ext
field of a Generic_core_extensible.closure
when trying to extend a type indexed function
with a case for a pattern that is already covered.type 'b
ty_fun = {
|
f : |
'b
is the code for a parametric type 'a f
such that 'b ty_fun
is equivalent to for all 'a . 'a f
type 'b
closure = {
|
f : |
(* | f : applies the extensible function.Raises Type_pattern_match_failure when the type index doesn't
match any of the patterns in the collection. | *) |
|
ext : |
(* | ext : extends the function with a new case. We must
provide a type pattern, (example: List Any ). The
ty_fun provided is only expected to handle types
matching with the pattern. Effectful.Raises Pattern_overwrite when called with a type pattern that
was already registered. | *) |
val create : string -> 'f closure
create name
, creates a new closure initially empty:
calling f
will raise
Type_pattern_match_failure
. The name is used in the exception messages. Effectful.