A computation is the type of an operation that can be applied to various different kind of types. It is expressed as a type with one parameter:
type 'a computation
Examples of computation:
type sexp_of_t = ('a -> Sexp.t) computation type type_struct = Type_struct.t computation
The term generic
is used to refer to a specific implementation of a computation
whose concrete implementation is programmed using the type representation of values.
For example, when one uses with sexp
as a way to implement the sexp_of_t
computation, the technique used is code generation at compile time. Another approach
is to define a generic function sexp_of_t
that inspects the representation of the
type at runtime.
This module offers an abstraction over type rep in order to implement generics in a efficient way.
Provided from a user enough pieces of implementation regarding a particular computation, this module returns essentially the following function:
(** main function : get the computation from the typerep *)
val of_typerep : 'a Typerep.t -> `generic of 'a computation
that allows one to get the generic computation operating on a given type 'a
.
Work in progress representation of a computation. This is mostly used to handle
recursive types. While building a computation on a recursive type, one needs to have
some computation available for the location where the type appears recursively.
init
will be called once on each new type_name met during the traversal of a type.
Each time the same type is encountered again, get_wip_computation
will be called.
At the end of the traversal of that particular type, set_final_computation
will be
called, offering as a way to "close" the wip representation. 'a t
can be mutable
(and is likely to be in practice).
After a set_final_computation
is performed and return a final computation C for a
type_name, C will be memoized and returned for each further occurrences of the same
type_name inside the typerep, going further on.
Mutable context used to memorize some info during the traversal of a typerep.
A new context is created before starting to enter the toplevel of a typerep.
Then it is passed to all init
calls that happen during the traversal of it.
The user of the generic functor is free to stuff there whatever context needs to be
available while creating a new value of type 'a Named.t
Not all computations are arrow types. For example:
'a computation = Type_struct.t
'a computation = Type_hash.t
However, arrow types computation such as of_sexp
, sexp_of
, json_of
, etc. are
such a standard case that is seems reasonable to share this extra layer of functor for
it to build the Named
module.
Runtime identifier for a generic computation. This is essentially a string whose purpose is to give reasonable error messages in case the dependency requirements for a generic are not met at runtime.
The field called required
is needed in order to build a generic computation module.
It is used to establish a set up that would explicitly list all the computation that
are required by an other computation to work.
Generic computations are a way to build dynamically some operations on types. It is possible to build computation on top of each other. This ident type will be the key to talk about other computations at the point of setting up the dependencies.
generic_ident * typename or info
Extending an existing generic for a particular type name
The use of first class modules there is essentially because we cannot talk about a variable of kind * -> k val register1 : 'a 't Typerep.t -> ('a computation -> 'a 't computation) -> unit ...
special less scary type when the type has no parameters. this is equivalent as using register0
main function : compute the generic computation from the typerep
exported to build a computation on top of a previous one
The name
is used for debug information only in case of Broken_dependency.
The required
is to handle dependencies between generics at runtime.
Example:
if X
is the module given to build a generic computation G
that depends on three
other computation A,B,C
then X.required shall be A.ident ; B.ident ; C.ident