/usr/lib/ocaml/typerep_lib/type_generic.mli is in libtyperep-camlp4-dev 113.00.00-3ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | open Std_internal
(** 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].
*)
module Variant_and_record_intf : (module type of Variant_and_record_intf)
module Helper (A : Variant_and_record_intf.S) (B : Variant_and_record_intf.S) : sig
type map = { map : 'a. 'a A.t -> 'a B.t }
val map_variant : map -> 'a A.Variant.t -> 'a B.Variant.t
val map_record : map -> 'a A.Record.t -> 'a B.Record.t
end
module type Named = sig
type 'a computation
module Context : sig
(**
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]
*)
type t
val create : unit -> t
end
(**
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.
*)
type 'a t
val init : Context.t -> 'a Typename.t -> 'a t
val get_wip_computation : 'a t -> 'a computation
val set_final_computation : 'a t -> 'a computation -> 'a computation
(**
It might be interesting to inline some computation for a few typerep if they appear
several times within a typerep. This parameters will allow one to
tweak the sharing between multiple occurences of the same typename.
[share = true] means no inlining.
Note that not sharing recursive types will lead the [of_typerep] function to loop
forever. Be careful when setting this.
An example where it is not suitable to share everything for example is
typestruct. The typestruct of an int is a simple constructor called [Int], naming it
once and using the name to refere to it later within the typestruct does not lead to
a shorter typestruct, and is in fact less readable. The benefit of the sharing
depends on the computation, its memory and building costs.
*)
val share : _ Typerep.t -> bool
end
module type Computation = sig
type 'a t
include Variant_and_record_intf.S with type 'a t := 'a t
val int : int t
val int32 : int32 t
val int64 : int64 t
val nativeint : nativeint t
val char : char t
val float : float t
val string : string t
val bool : bool t
val unit : unit t
val option : 'a t -> 'a option t
val list : 'a t -> 'a list t
val array : 'a t -> 'a array t
val lazy_t : 'a t -> 'a lazy_t t
val ref_ : 'a t -> 'a ref t
val function_ : 'a t -> 'b t -> ('a -> 'b) t
val tuple2 : 'a t -> 'b t -> ('a * 'b) t
val tuple3 : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t
val tuple4 : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t
val tuple5 : 'a t -> 'b t -> 'c t -> 'd t -> 'e t -> ('a * 'b * 'c * 'd * 'e) t
val record : 'a Record.t -> 'a t
val variant : 'a Variant.t -> 'a t
module Named : Named with type 'a computation := 'a t
end
(**
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.
*)
module Make_named_for_closure (X : sig
type 'a input
type 'a output
type 'a t = 'a input -> 'a output
end) : Named with type 'a computation := 'a X.t
module Ident : sig
(**
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.
*)
type t
end
module type S = sig
type 'a t
type 'a computation = 'a t
val ident : Ident.t
(** generic_ident * typename or info *)
exception Not_implemented of string * string
(** register mechanism to customize the behavior of this generic *)
include Type_generic_intf.S with type 'a t := 'a t
(**
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
...
*)
val register0 : (module S0) -> unit
val register1 : (module S1) -> unit
val register2 : (module S2) -> unit
val register3 : (module S3) -> unit
val register4 : (module S4) -> unit
val register5 : (module S5) -> unit
(**
special less scary type when the type has no parameters. this is equivalent as
using register0
*)
val register : 'a Typerep.t -> 'a computation -> unit
(** main function : compute the generic computation from the typerep *)
val of_typerep : 'a Typerep.t -> [ `generic of 'a computation ]
(** exported to build a computation on top of a previous one *)
module Computation : Computation with type 'a t = 'a t
end
(**
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 ]
*)
module Make (X : sig
type 'a t
val name : string
val required : Ident.t list
include Computation
with type 'a t := 'a t
end) : S with type 'a t = 'a X.t
|