mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
fixpoint operators for Conv
This commit is contained in:
parent
a523c63c7f
commit
8edb20ceee
2 changed files with 57 additions and 17 deletions
55
conv.ml
55
conv.ml
|
|
@ -28,6 +28,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
exception ConversionFailure of string
|
exception ConversionFailure of string
|
||||||
|
|
||||||
|
let (@@@) a b = a b
|
||||||
|
|
||||||
(* error-raising function *)
|
(* error-raising function *)
|
||||||
let __error msg =
|
let __error msg =
|
||||||
let b = Buffer.create 15 in
|
let b = Buffer.create 15 in
|
||||||
|
|
@ -50,6 +52,7 @@ module Sink = struct
|
||||||
| Tuple : 'a tuple_sink -> 'a t
|
| Tuple : 'a tuple_sink -> 'a t
|
||||||
| Sum : (string -> ('b t -> 'b) -> 'a) -> 'a t
|
| Sum : (string -> ('b t -> 'b) -> 'a) -> 'a t
|
||||||
| Map : 'a t * ('a -> 'b) -> 'b t
|
| Map : 'a t * ('a -> 'b) -> 'b t
|
||||||
|
| Fix : ('a t -> 'a t) -> 'a t
|
||||||
|
|
||||||
and 'r record_sink =
|
and 'r record_sink =
|
||||||
| RecordField : string * 'a t * ('a -> 'r record_sink) -> 'r record_sink
|
| RecordField : string * 'a t * ('a -> 'r record_sink) -> 'r record_sink
|
||||||
|
|
@ -73,6 +76,7 @@ module Sink = struct
|
||||||
| Tuple _ -> "tuple"
|
| Tuple _ -> "tuple"
|
||||||
| Sum _ -> "sum"
|
| Sum _ -> "sum"
|
||||||
| Map (sink', _) -> __expected sink'
|
| Map (sink', _) -> __expected sink'
|
||||||
|
| (Fix f) as sink -> __expected (f sink)
|
||||||
|
|
||||||
let __id x = x
|
let __id x = x
|
||||||
|
|
||||||
|
|
@ -92,6 +96,8 @@ module Sink = struct
|
||||||
let (|:|) (name,sink) cont = RecordField (name,sink,cont)
|
let (|:|) (name,sink) cont = RecordField (name,sink,cont)
|
||||||
let yield_record r = RecordStop r
|
let yield_record r = RecordStop r
|
||||||
let record r = Record r
|
let record r = Record r
|
||||||
|
let record_fix f =
|
||||||
|
Fix (fun r -> Record (f r))
|
||||||
|
|
||||||
let (|+|) sink cont = TupleField (sink, cont)
|
let (|+|) sink cont = TupleField (sink, cont)
|
||||||
let yield_tuple t = TupleStop t
|
let yield_tuple t = TupleStop t
|
||||||
|
|
@ -122,6 +128,9 @@ module Sink = struct
|
||||||
)
|
)
|
||||||
|
|
||||||
let sum f = Sum f
|
let sum f = Sum f
|
||||||
|
let sum_fix f =
|
||||||
|
Fix (fun s -> Sum (f s))
|
||||||
|
|
||||||
let opt sink = sum (fun name cont ->
|
let opt sink = sum (fun name cont ->
|
||||||
match name with
|
match name with
|
||||||
| "some" -> Some (cont sink)
|
| "some" -> Some (cont sink)
|
||||||
|
|
@ -155,6 +164,7 @@ module Source = struct
|
||||||
| Tuple : 'a tuple_src -> 'a t
|
| Tuple : 'a tuple_src -> 'a t
|
||||||
| Sum : ('a -> string * sum_src) -> 'a t
|
| Sum : ('a -> string * sum_src) -> 'a t
|
||||||
| Map : 'a t * ('b -> 'a) -> 'b t
|
| Map : 'a t * ('b -> 'a) -> 'b t
|
||||||
|
| Fix : ('a t -> 'a t) -> 'a t
|
||||||
|
|
||||||
and 'r record_src =
|
and 'r record_src =
|
||||||
| RecordField : string * ('r -> 'a) * 'a t * 'r record_src -> 'r record_src
|
| RecordField : string * ('r -> 'a) * 'a t * 'r record_src -> 'r record_src
|
||||||
|
|
@ -182,7 +192,8 @@ module Source = struct
|
||||||
RecordField (name,get,src',cont)
|
RecordField (name,get,src',cont)
|
||||||
let record_stop = RecordStop
|
let record_stop = RecordStop
|
||||||
let record r = Record r
|
let record r = Record r
|
||||||
let (@@@) a b = a b
|
let record_fix f =
|
||||||
|
Fix (fun r -> Record (f r))
|
||||||
|
|
||||||
let tuple_field src get cont = TupleField (src,get,cont)
|
let tuple_field src get cont = TupleField (src,get,cont)
|
||||||
let tuple_stop = TupleStop
|
let tuple_stop = TupleStop
|
||||||
|
|
@ -209,6 +220,8 @@ module Source = struct
|
||||||
let sum_nil = SumNil
|
let sum_nil = SumNil
|
||||||
let sum_cons src' x tl = SumCons (src', x, tl)
|
let sum_cons src' x tl = SumCons (src', x, tl)
|
||||||
let sum f = Sum f
|
let sum f = Sum f
|
||||||
|
let sum_fix f =
|
||||||
|
Fix (fun s -> Sum (f s))
|
||||||
|
|
||||||
let opt src = sum (function
|
let opt src = sum (function
|
||||||
| Some x -> "some", sum_cons src x sum_nil
|
| Some x -> "some", sum_cons src x sum_nil
|
||||||
|
|
@ -226,6 +239,7 @@ module Source = struct
|
||||||
| Sink.Unit u -> u
|
| Sink.Unit u -> u
|
||||||
| Sink.Int f -> f 0
|
| Sink.Int f -> f 0
|
||||||
| Sink.Map (sink', f) -> f (self#unit_ sink')
|
| Sink.Map (sink', f) -> f (self#unit_ sink')
|
||||||
|
| Sink.Fix f -> self#unit_ (f sink)
|
||||||
| _ -> __error "get Unit, but expected %s" (Sink.__expected sink)
|
| _ -> __error "get Unit, but expected %s" (Sink.__expected sink)
|
||||||
|
|
||||||
method private bool_ : 'b. 'b Sink.t -> bool -> 'b
|
method private bool_ : 'b. 'b Sink.t -> bool -> 'b
|
||||||
|
|
@ -234,6 +248,7 @@ module Source = struct
|
||||||
| Sink.Int f -> f (if b then 1 else 0)
|
| Sink.Int f -> f (if b then 1 else 0)
|
||||||
| Sink.String f -> f (string_of_bool b)
|
| Sink.String f -> f (string_of_bool b)
|
||||||
| Sink.Map (sink', f) -> f (self#bool_ sink' b)
|
| Sink.Map (sink', f) -> f (self#bool_ sink' b)
|
||||||
|
| Sink.Fix f -> self#bool_ (f sink) b
|
||||||
| _ -> __error "get Bool, but expected %s" (Sink.__expected sink)
|
| _ -> __error "get Bool, but expected %s" (Sink.__expected sink)
|
||||||
|
|
||||||
method private float_ : 'b. 'b Sink.t -> float -> 'b
|
method private float_ : 'b. 'b Sink.t -> float -> 'b
|
||||||
|
|
@ -241,6 +256,7 @@ module Source = struct
|
||||||
| Sink.Float f -> f x
|
| Sink.Float f -> f x
|
||||||
| Sink.String f -> f (string_of_float x)
|
| Sink.String f -> f (string_of_float x)
|
||||||
| Sink.Map (sink', f) -> f (self#float_ sink' x)
|
| Sink.Map (sink', f) -> f (self#float_ sink' x)
|
||||||
|
| Sink.Fix f -> self#float_ (f sink) x
|
||||||
| _ -> __error "get Float, but expected %s" (Sink.__expected sink)
|
| _ -> __error "get Float, but expected %s" (Sink.__expected sink)
|
||||||
|
|
||||||
method private int_ : 'b. 'b Sink.t -> int -> 'b
|
method private int_ : 'b. 'b Sink.t -> int -> 'b
|
||||||
|
|
@ -248,6 +264,7 @@ module Source = struct
|
||||||
| Sink.Int f -> f i
|
| Sink.Int f -> f i
|
||||||
| Sink.String f -> f (string_of_int i)
|
| Sink.String f -> f (string_of_int i)
|
||||||
| Sink.Map (sink', f) -> f (self#int_ sink' i)
|
| Sink.Map (sink', f) -> f (self#int_ sink' i)
|
||||||
|
| Sink.Fix f -> self#int_ (f sink) i
|
||||||
| _ -> __error "get Int, but expected %s" (Sink.__expected sink)
|
| _ -> __error "get Int, but expected %s" (Sink.__expected sink)
|
||||||
|
|
||||||
method private string_ : 'b. 'b Sink.t -> string -> 'b
|
method private string_ : 'b. 'b Sink.t -> string -> 'b
|
||||||
|
|
@ -258,6 +275,7 @@ module Source = struct
|
||||||
with Invalid_argument _ -> __error "get String, but expected Int"
|
with Invalid_argument _ -> __error "get String, but expected Int"
|
||||||
end
|
end
|
||||||
| Sink.Map (sink', f) -> f (self#string_ sink' s)
|
| Sink.Map (sink', f) -> f (self#string_ sink' s)
|
||||||
|
| Sink.Fix f -> self#string_ (f sink) s
|
||||||
| _ -> __error "get String, but expected %s" (Sink.__expected sink)
|
| _ -> __error "get String, but expected %s" (Sink.__expected sink)
|
||||||
|
|
||||||
method private list_ : 'b. 'b Sink.t -> 'a list -> 'b
|
method private list_ : 'b. 'b Sink.t -> 'a list -> 'b
|
||||||
|
|
@ -265,6 +283,7 @@ module Source = struct
|
||||||
| Sink.List f ->
|
| Sink.List f ->
|
||||||
f (fun sink' -> List.map (self#visit sink') l)
|
f (fun sink' -> List.map (self#visit sink') l)
|
||||||
| Sink.Map (sink', f) -> f (self#list_ sink' l)
|
| Sink.Map (sink', f) -> f (self#list_ sink' l)
|
||||||
|
| Sink.Fix f -> self#list_ (f sink) l
|
||||||
| _ -> __error "get List, but expected %s" (Sink.__expected sink)
|
| _ -> __error "get List, but expected %s" (Sink.__expected sink)
|
||||||
|
|
||||||
method private record : 'b. 'b Sink.t -> (string*'a) list -> 'b
|
method private record : 'b. 'b Sink.t -> (string*'a) list -> 'b
|
||||||
|
|
@ -280,6 +299,7 @@ module Source = struct
|
||||||
build_record (cont sink_field)
|
build_record (cont sink_field)
|
||||||
in build_record r
|
in build_record r
|
||||||
| Sink.Map (sink', f) -> f (self#record sink' l)
|
| Sink.Map (sink', f) -> f (self#record sink' l)
|
||||||
|
| Sink.Fix f -> self#record (f sink) l
|
||||||
| _ -> __error "get Record, but expected %s" (Sink.__expected sink)
|
| _ -> __error "get Record, but expected %s" (Sink.__expected sink)
|
||||||
|
|
||||||
method private tuple : 'b. 'b Sink.t -> 'a list -> 'b
|
method private tuple : 'b. 'b Sink.t -> 'a list -> 'b
|
||||||
|
|
@ -298,6 +318,7 @@ module Source = struct
|
||||||
build_tuple l' (cont y)
|
build_tuple l' (cont y)
|
||||||
in build_tuple l t_sink
|
in build_tuple l t_sink
|
||||||
| Sink.Map (sink', f) -> f (self#tuple sink' l)
|
| Sink.Map (sink', f) -> f (self#tuple sink' l)
|
||||||
|
| Sink.Fix f -> self#tuple (f sink) l
|
||||||
| _ -> __error "get Tuple, but expected %s" (Sink.__expected sink)
|
| _ -> __error "get Tuple, but expected %s" (Sink.__expected sink)
|
||||||
|
|
||||||
method private sum : 'b. 'b Sink.t -> string -> 'a -> 'b
|
method private sum : 'b. 'b Sink.t -> string -> 'a -> 'b
|
||||||
|
|
@ -305,6 +326,7 @@ module Source = struct
|
||||||
| Sink.Sum f ->
|
| Sink.Sum f ->
|
||||||
f name (fun sink' -> self#visit sink' s)
|
f name (fun sink' -> self#visit sink' s)
|
||||||
| Sink.Map (sink', f) -> f (self#sum sink' name s)
|
| Sink.Map (sink', f) -> f (self#sum sink' name s)
|
||||||
|
| Sink.Fix f -> self#sum (f sink) name s
|
||||||
| _ -> __error "get Sum(%s), but expected %s" name (Sink.__expected sink)
|
| _ -> __error "get Sum(%s), but expected %s" name (Sink.__expected sink)
|
||||||
|
|
||||||
method virtual visit : 'b. 'b Sink.t -> 'a -> 'b
|
method virtual visit : 'b. 'b Sink.t -> 'a -> 'b
|
||||||
|
|
@ -348,6 +370,9 @@ let rec into : type a b. a Source.t -> b Sink.universal -> a -> b =
|
||||||
let name, sum = f x in
|
let name, sum = f x in
|
||||||
conv_sum name [] sum
|
conv_sum name [] sum
|
||||||
| Source.Map (src', f) -> into src' sink (f x)
|
| Source.Map (src', f) -> into src' sink (f x)
|
||||||
|
| Source.Fix f ->
|
||||||
|
let src' = f src in
|
||||||
|
into src' sink x
|
||||||
|
|
||||||
let from (src:'a Source.universal) (sink:'b Sink.t) (x:'a) : 'b = src#visit sink x
|
let from (src:'a Source.universal) (sink:'b Sink.t) (x:'a) : 'b = src#visit sink x
|
||||||
|
|
||||||
|
|
@ -397,26 +422,32 @@ type point = {
|
||||||
x:int;
|
x:int;
|
||||||
y:int;
|
y:int;
|
||||||
color:string;
|
color:string;
|
||||||
|
prev : point option; (* previous position, say *)
|
||||||
}
|
}
|
||||||
|
|
||||||
let point_sink =
|
let rec point_sink =
|
||||||
Sink.(record (
|
Sink.(record_fix
|
||||||
|
(fun self ->
|
||||||
"x" --> int_ |:| fun x ->
|
"x" --> int_ |:| fun x ->
|
||||||
"y" --> int_ |:| fun y ->
|
"y" --> int_ |:| fun y ->
|
||||||
"color" --> string_ |:| fun color ->
|
"color" --> string_ |:| fun color ->
|
||||||
yield_record {x;y;color}
|
"prev" --> (opt self) |:| fun prev ->
|
||||||
))
|
yield_record {x;y;color;prev}
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
let point_source : point Source.t =
|
let point_source : point Source.t =
|
||||||
Source.(record (
|
Source.(record_fix
|
||||||
record_field "x" (fun p -> p.x) int_ @@@
|
(fun self ->
|
||||||
record_field "y" (fun p -> p.y) int_ @@@
|
record_field "x" (fun p -> p.x) int_ @@@
|
||||||
record_field "color" (fun p -> p.color) string_ @@@
|
record_field "y" (fun p -> p.y) int_ @@@
|
||||||
record_stop
|
record_field "color" (fun p -> p.color) string_ @@@
|
||||||
))
|
record_field "prev" (fun p -> p.prev) (opt self) @@@
|
||||||
|
record_stop
|
||||||
|
))
|
||||||
|
|
||||||
let p = {x=1; y=42; color="yellow"; }
|
let p = {x=1; y=42; color="yellow";
|
||||||
|
prev = Some {x=1; y=41; color="red"; prev=None};}
|
||||||
|
|
||||||
let p2 = into point_source Json.sink p
|
let p2 = into point_source Json.sink p
|
||||||
(* TODO tests *)
|
(* TODO tests *)
|
||||||
|
|
|
||||||
19
conv.mli
19
conv.mli
|
|
@ -28,12 +28,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
exception ConversionFailure of string
|
exception ConversionFailure of string
|
||||||
|
|
||||||
|
val (@@@) : ('a -> 'b) -> 'a -> 'b
|
||||||
|
|
||||||
(** {6 Sinks}
|
(** {6 Sinks}
|
||||||
A sink is used to traverse values of some type 'a *)
|
A sink is used to traverse values of some type 'a *)
|
||||||
module Sink : sig
|
module Sink : sig
|
||||||
(** A specific sink that requires a given shape to produce
|
(** A specific sink that requires a given shape to produce
|
||||||
* a value of type 'a *)
|
a value of type 'a *)
|
||||||
type 'a t =
|
type 'a t = private
|
||||||
| Unit : 'a -> 'a t
|
| Unit : 'a -> 'a t
|
||||||
| Bool : (bool -> 'a) -> 'a t
|
| Bool : (bool -> 'a) -> 'a t
|
||||||
| Float : (float -> 'a) -> 'a t
|
| Float : (float -> 'a) -> 'a t
|
||||||
|
|
@ -44,6 +46,7 @@ module Sink : sig
|
||||||
| Tuple : 'a tuple_sink -> 'a t
|
| Tuple : 'a tuple_sink -> 'a t
|
||||||
| Sum : (string -> ('b t -> 'b) -> 'a) -> 'a t
|
| Sum : (string -> ('b t -> 'b) -> 'a) -> 'a t
|
||||||
| Map : 'a t * ('a -> 'b) -> 'b t
|
| Map : 'a t * ('a -> 'b) -> 'b t
|
||||||
|
| Fix : ('a t -> 'a t) -> 'a t
|
||||||
|
|
||||||
and 'r record_sink =
|
and 'r record_sink =
|
||||||
| RecordField : string * 'a t * ('a -> 'r record_sink) -> 'r record_sink
|
| RecordField : string * 'a t * ('a -> 'r record_sink) -> 'r record_sink
|
||||||
|
|
@ -70,6 +73,7 @@ module Sink : sig
|
||||||
val (|:|) : (string * 'a t) -> ('a -> 'r record_sink) -> 'r record_sink
|
val (|:|) : (string * 'a t) -> ('a -> 'r record_sink) -> 'r record_sink
|
||||||
val yield_record : 'r -> 'r record_sink
|
val yield_record : 'r -> 'r record_sink
|
||||||
val record : 'r record_sink -> 'r t
|
val record : 'r record_sink -> 'r t
|
||||||
|
val record_fix : ('r t -> 'r record_sink) -> 'r t
|
||||||
|
|
||||||
val (|+|) : 'a t -> ('a -> 't tuple_sink) -> 't tuple_sink
|
val (|+|) : 'a t -> ('a -> 't tuple_sink) -> 't tuple_sink
|
||||||
val yield_tuple : 't -> 't tuple_sink
|
val yield_tuple : 't -> 't tuple_sink
|
||||||
|
|
@ -80,6 +84,8 @@ module Sink : sig
|
||||||
val quad : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t
|
val quad : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t
|
||||||
|
|
||||||
val sum : (string -> ('b t -> 'b) -> 'a) -> 'a t
|
val sum : (string -> ('b t -> 'b) -> 'a) -> 'a t
|
||||||
|
val sum_fix : ('a t -> string -> ('b t -> 'b) -> 'a) -> 'a t
|
||||||
|
|
||||||
val opt : 'a t -> 'a option t
|
val opt : 'a t -> 'a option t
|
||||||
|
|
||||||
(** Universal sink, such as a serialization format *)
|
(** Universal sink, such as a serialization format *)
|
||||||
|
|
@ -100,7 +106,7 @@ end
|
||||||
A source is used to build values of some type 'a *)
|
A source is used to build values of some type 'a *)
|
||||||
module Source : sig
|
module Source : sig
|
||||||
(** A specific source that follows the shape of the type 'a *)
|
(** A specific source that follows the shape of the type 'a *)
|
||||||
type 'a t =
|
type 'a t = private
|
||||||
| Unit : unit t
|
| Unit : unit t
|
||||||
| Bool : bool t
|
| Bool : bool t
|
||||||
| Float : float t
|
| Float : float t
|
||||||
|
|
@ -111,6 +117,7 @@ module Source : sig
|
||||||
| Tuple : 'a tuple_src -> 'a t
|
| Tuple : 'a tuple_src -> 'a t
|
||||||
| Sum : ('a -> string * sum_src) -> 'a t
|
| Sum : ('a -> string * sum_src) -> 'a t
|
||||||
| Map : 'a t * ('b -> 'a) -> 'b t
|
| Map : 'a t * ('b -> 'a) -> 'b t
|
||||||
|
| Fix : ('a t -> 'a t) -> 'a t
|
||||||
|
|
||||||
and 'r record_src =
|
and 'r record_src =
|
||||||
| RecordField : string * ('r -> 'a) * 'a t * 'r record_src -> 'r record_src
|
| RecordField : string * ('r -> 'a) * 'a t * 'r record_src -> 'r record_src
|
||||||
|
|
@ -131,14 +138,13 @@ module Source : sig
|
||||||
val string_ : string t
|
val string_ : string t
|
||||||
val list_ : 'a t -> 'a list t
|
val list_ : 'a t -> 'a list t
|
||||||
|
|
||||||
val (@@@) : ('a -> 'b) -> 'a -> 'b
|
|
||||||
|
|
||||||
val map : ('b -> 'a) -> 'a t -> 'b t
|
val map : ('b -> 'a) -> 'a t -> 'b t
|
||||||
val array_ : 'a t -> 'a array t
|
val array_ : 'a t -> 'a array t
|
||||||
|
|
||||||
val record_field : string -> ('r -> 'a) -> 'a t -> 'r record_src -> 'r record_src
|
val record_field : string -> ('r -> 'a) -> 'a t -> 'r record_src -> 'r record_src
|
||||||
val record_stop : 'r record_src
|
val record_stop : 'r record_src
|
||||||
val record : 'r record_src -> 'r t
|
val record : 'r record_src -> 'r t
|
||||||
|
val record_fix : ('r t -> 'r record_src) -> 'r t
|
||||||
|
|
||||||
val tuple_field : 'a t -> ('t -> 'a) -> 't tuple_src -> 't tuple_src
|
val tuple_field : 'a t -> ('t -> 'a) -> 't tuple_src -> 't tuple_src
|
||||||
val tuple_stop : 't tuple_src
|
val tuple_stop : 't tuple_src
|
||||||
|
|
@ -151,6 +157,7 @@ module Source : sig
|
||||||
val sum_nil : sum_src
|
val sum_nil : sum_src
|
||||||
val sum_cons : 'a t -> 'a -> sum_src -> sum_src
|
val sum_cons : 'a t -> 'a -> sum_src -> sum_src
|
||||||
val sum : ('a -> string * sum_src) -> 'a t
|
val sum : ('a -> string * sum_src) -> 'a t
|
||||||
|
val sum_fix : ('a t -> 'a -> string * sum_src) -> 'a t
|
||||||
|
|
||||||
val opt : 'a t -> 'a option t
|
val opt : 'a t -> 'a option t
|
||||||
|
|
||||||
|
|
@ -194,3 +201,5 @@ module Json : sig
|
||||||
val source : t Source.universal
|
val source : t Source.universal
|
||||||
val sink : t Sink.universal
|
val sink : t Sink.universal
|
||||||
end
|
end
|
||||||
|
|
||||||
|
val p2 : Json.t
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue