260 lines
8.8 KiB
OCaml
260 lines
8.8 KiB
OCaml
|
|
module T = struct
|
||
|
|
type 'a map = 'a -> 'a
|
||
|
|
type 'a iter = 'a -> unit
|
||
|
|
type ('a, 'acc) fold = 'a -> 'acc -> 'acc
|
||
|
|
type ('a, 'acc) fold_map = 'a -> 'acc -> 'a * 'acc
|
||
|
|
type ('ctx, 'a) map_with_context = 'ctx -> 'a -> 'a
|
||
|
|
type ('a, 'res) lift = 'a -> 'res
|
||
|
|
type ('ctx, 'a, 'res) lift_map_with_context = 'ctx -> 'a -> 'a * 'res
|
||
|
|
end
|
||
|
|
|
||
|
|
class map =
|
||
|
|
let any x = x in
|
||
|
|
object
|
||
|
|
method int : int T.map = any
|
||
|
|
method string : string T.map = any
|
||
|
|
method bool : bool T.map = any
|
||
|
|
method char : char T.map = any
|
||
|
|
|
||
|
|
method option : 'a. 'a T.map -> 'a option T.map =
|
||
|
|
fun f x -> match x with None -> None | Some x -> Some (f x)
|
||
|
|
|
||
|
|
method list : 'a. 'a T.map -> 'a list T.map = List.map
|
||
|
|
method array : 'a. 'a T.map -> 'a array T.map = Array.map
|
||
|
|
end
|
||
|
|
|
||
|
|
class iter =
|
||
|
|
let any = ignore in
|
||
|
|
object
|
||
|
|
method int : int T.iter = any
|
||
|
|
method string : string T.iter = any
|
||
|
|
method bool : bool T.iter = any
|
||
|
|
method char : char T.iter = any
|
||
|
|
|
||
|
|
method option : 'a. 'a T.iter -> 'a option T.iter =
|
||
|
|
fun f x -> match x with None -> () | Some x -> f x
|
||
|
|
|
||
|
|
method list : 'a. 'a T.iter -> 'a list T.iter = List.iter
|
||
|
|
method array : 'a. 'a T.iter -> 'a array T.iter = Array.iter
|
||
|
|
end
|
||
|
|
|
||
|
|
class ['acc] fold =
|
||
|
|
let any _ acc = acc in
|
||
|
|
object
|
||
|
|
method int : (int, 'acc) T.fold = any
|
||
|
|
method string : (string, 'acc) T.fold = any
|
||
|
|
method bool : (bool, 'acc) T.fold = any
|
||
|
|
method char : (char, 'acc) T.fold = any
|
||
|
|
|
||
|
|
method option : 'a. ('a, 'acc) T.fold -> ('a option, 'acc) T.fold =
|
||
|
|
fun f x acc -> match x with None -> acc | Some x -> f x acc
|
||
|
|
|
||
|
|
method list : 'a. ('a, 'acc) T.fold -> ('a list, 'acc) T.fold =
|
||
|
|
let rec loop f l acc =
|
||
|
|
match l with [] -> acc | x :: l -> loop f l (f x acc)
|
||
|
|
in
|
||
|
|
loop
|
||
|
|
|
||
|
|
method array : 'a. ('a, 'acc) T.fold -> ('a array, 'acc) T.fold =
|
||
|
|
fun f a acc ->
|
||
|
|
let r = ref acc in
|
||
|
|
for i = 0 to Array.length a - 1 do
|
||
|
|
r := f (Array.unsafe_get a i) !r
|
||
|
|
done;
|
||
|
|
!r
|
||
|
|
end
|
||
|
|
|
||
|
|
class ['acc] fold_map =
|
||
|
|
let any x acc = (x, acc) in
|
||
|
|
object
|
||
|
|
method int : (int, 'acc) T.fold_map = any
|
||
|
|
method string : (string, 'acc) T.fold_map = any
|
||
|
|
method bool : (bool, 'acc) T.fold_map = any
|
||
|
|
method char : (char, 'acc) T.fold_map = any
|
||
|
|
|
||
|
|
method option : 'a. ('a, 'acc) T.fold_map -> ('a option, 'acc) T.fold_map =
|
||
|
|
fun f x acc ->
|
||
|
|
match x with
|
||
|
|
| None -> (None, acc)
|
||
|
|
| Some x ->
|
||
|
|
let x, acc = f x acc in
|
||
|
|
(Some x, acc)
|
||
|
|
|
||
|
|
method list : 'a. ('a, 'acc) T.fold_map -> ('a list, 'acc) T.fold_map =
|
||
|
|
let rec loop f l acc =
|
||
|
|
match l with
|
||
|
|
| [] -> ([], acc)
|
||
|
|
| x :: l ->
|
||
|
|
let x, acc = f x acc in
|
||
|
|
let l, acc = loop f l acc in
|
||
|
|
(x :: l, acc)
|
||
|
|
in
|
||
|
|
loop
|
||
|
|
|
||
|
|
method array : 'a. ('a, 'acc) T.fold_map -> ('a array, 'acc) T.fold_map =
|
||
|
|
fun f a acc ->
|
||
|
|
let len = Array.length a in
|
||
|
|
if len = 0 then (a, acc)
|
||
|
|
else
|
||
|
|
let x, acc = f (Array.unsafe_get a 0) acc in
|
||
|
|
let a' = Array.make len x in
|
||
|
|
let r = ref acc in
|
||
|
|
for i = 1 to len - 1 do
|
||
|
|
let x, acc = f (Array.unsafe_get a i) !r in
|
||
|
|
Array.unsafe_set a' i x;
|
||
|
|
r := acc
|
||
|
|
done;
|
||
|
|
(a', !r)
|
||
|
|
end
|
||
|
|
|
||
|
|
class ['ctx] map_with_context =
|
||
|
|
let any _ x = x in
|
||
|
|
object
|
||
|
|
method int : ('ctx, int) T.map_with_context = any
|
||
|
|
method string : ('ctx, string) T.map_with_context = any
|
||
|
|
method bool : ('ctx, bool) T.map_with_context = any
|
||
|
|
method char : ('ctx, char) T.map_with_context = any
|
||
|
|
|
||
|
|
method option :
|
||
|
|
'a.
|
||
|
|
('ctx, 'a) T.map_with_context -> ('ctx, 'a option) T.map_with_context =
|
||
|
|
fun f ctx x -> match x with None -> None | Some x -> Some (f ctx x)
|
||
|
|
|
||
|
|
method list :
|
||
|
|
'a. ('ctx, 'a) T.map_with_context -> ('ctx, 'a list) T.map_with_context
|
||
|
|
=
|
||
|
|
fun f ctx l -> List.map (f ctx) l
|
||
|
|
|
||
|
|
method array :
|
||
|
|
'a. ('ctx, 'a) T.map_with_context -> ('ctx, 'a array) T.map_with_context
|
||
|
|
=
|
||
|
|
fun f ctx a -> Array.map (f ctx) a
|
||
|
|
end
|
||
|
|
|
||
|
|
class virtual ['res] lift =
|
||
|
|
object (self)
|
||
|
|
method virtual other : 'a. ('a, 'res) T.lift
|
||
|
|
method virtual int : (int, 'res) T.lift
|
||
|
|
method virtual string : (string, 'res) T.lift
|
||
|
|
method virtual bool : (bool, 'res) T.lift
|
||
|
|
method virtual char : (char, 'res) T.lift
|
||
|
|
method virtual array : 'a. ('a, 'res) T.lift -> ('a array, 'res) T.lift
|
||
|
|
method virtual float : (float, 'res) T.lift
|
||
|
|
method virtual int32 : (int32, 'res) T.lift
|
||
|
|
method virtual int64 : (int64, 'res) T.lift
|
||
|
|
method virtual nativeint : (nativeint, 'res) T.lift
|
||
|
|
method virtual unit : (unit, 'res) T.lift
|
||
|
|
method virtual record : (string * 'res) list -> 'res
|
||
|
|
method virtual constr : string -> 'res list -> 'res
|
||
|
|
method virtual tuple : 'res list -> 'res
|
||
|
|
|
||
|
|
method option : 'a. ('a, 'res) T.lift -> ('a option, 'res) T.lift =
|
||
|
|
fun f x ->
|
||
|
|
match x with
|
||
|
|
| None -> self#constr "None" []
|
||
|
|
| Some x -> self#constr "Some" [ f x ]
|
||
|
|
|
||
|
|
method list : 'a. ('a, 'res) T.lift -> ('a list, 'res) T.lift =
|
||
|
|
fun f l ->
|
||
|
|
match l with
|
||
|
|
| [] -> self#constr "[]" []
|
||
|
|
| x :: l -> self#constr "::" [ f x; self#list f l ]
|
||
|
|
end
|
||
|
|
|
||
|
|
class virtual ['ctx, 'res] lift_map_with_context =
|
||
|
|
object (self)
|
||
|
|
method virtual other : 'a. 'ctx -> 'a -> 'res
|
||
|
|
method virtual int : ('ctx, int, 'res) T.lift_map_with_context
|
||
|
|
method virtual string : ('ctx, string, 'res) T.lift_map_with_context
|
||
|
|
method virtual bool : ('ctx, bool, 'res) T.lift_map_with_context
|
||
|
|
method virtual char : ('ctx, char, 'res) T.lift_map_with_context
|
||
|
|
|
||
|
|
method virtual array
|
||
|
|
: 'a.
|
||
|
|
('ctx, 'a, 'res) T.lift_map_with_context ->
|
||
|
|
('ctx, 'a array, 'res) T.lift_map_with_context
|
||
|
|
|
||
|
|
method virtual float : ('ctx, float, 'res) T.lift_map_with_context
|
||
|
|
method virtual int32 : ('ctx, int32, 'res) T.lift_map_with_context
|
||
|
|
method virtual int64 : ('ctx, int64, 'res) T.lift_map_with_context
|
||
|
|
method virtual nativeint : ('ctx, nativeint, 'res) T.lift_map_with_context
|
||
|
|
method virtual unit : ('ctx, unit, 'res) T.lift_map_with_context
|
||
|
|
method virtual record : 'ctx -> (string * 'res) list -> 'res
|
||
|
|
method virtual constr : 'ctx -> string -> 'res list -> 'res
|
||
|
|
method virtual tuple : 'ctx -> 'res list -> 'res
|
||
|
|
|
||
|
|
method option :
|
||
|
|
'a.
|
||
|
|
('ctx, 'a, 'res) T.lift_map_with_context ->
|
||
|
|
('ctx, 'a option, 'res) T.lift_map_with_context =
|
||
|
|
fun f ctx x ->
|
||
|
|
match x with
|
||
|
|
| None -> (None, self#constr ctx "None" [])
|
||
|
|
| Some x ->
|
||
|
|
let x, res = f ctx x in
|
||
|
|
(Some x, self#constr ctx "Some" [ res ])
|
||
|
|
|
||
|
|
method list :
|
||
|
|
'a.
|
||
|
|
('ctx, 'a, 'res) T.lift_map_with_context ->
|
||
|
|
('ctx, 'a list, 'res) T.lift_map_with_context =
|
||
|
|
fun f ctx l ->
|
||
|
|
match l with
|
||
|
|
| [] -> ([], self#constr ctx "[]" [])
|
||
|
|
| x :: l ->
|
||
|
|
let x, res_head = f ctx x in
|
||
|
|
let l, res_tail = self#list f ctx l in
|
||
|
|
(x :: l, self#constr ctx "::" [ res_head; res_tail ])
|
||
|
|
end
|
||
|
|
|
||
|
|
class type ['res] std_lifters = object
|
||
|
|
method other : 'a. ('a, 'res) T.lift
|
||
|
|
method int : (int, 'res) T.lift
|
||
|
|
method string : (string, 'res) T.lift
|
||
|
|
method bool : (bool, 'res) T.lift
|
||
|
|
method char : (char, 'res) T.lift
|
||
|
|
method array : 'a. ('a, 'res) T.lift -> ('a array, 'res) T.lift
|
||
|
|
method record : (string * 'res) list -> 'res
|
||
|
|
method constr : string -> 'res list -> 'res
|
||
|
|
method tuple : 'res list -> 'res
|
||
|
|
method float : (float, 'res) T.lift
|
||
|
|
method int32 : (int32, 'res) T.lift
|
||
|
|
method int64 : (int64, 'res) T.lift
|
||
|
|
method nativeint : (nativeint, 'res) T.lift
|
||
|
|
method unit : (unit, 'res) T.lift
|
||
|
|
method option : 'a. ('a, 'res) T.lift -> ('a option, 'res) T.lift
|
||
|
|
method list : 'a. ('a, 'res) T.lift -> ('a list, 'res) T.lift
|
||
|
|
end
|
||
|
|
|
||
|
|
class type ['ctx, 'res] std_lift_mappers_with_context = object
|
||
|
|
method other : 'a. 'ctx -> 'a -> 'res
|
||
|
|
method int : ('ctx, int, 'res) T.lift_map_with_context
|
||
|
|
method string : ('ctx, string, 'res) T.lift_map_with_context
|
||
|
|
method bool : ('ctx, bool, 'res) T.lift_map_with_context
|
||
|
|
method char : ('ctx, char, 'res) T.lift_map_with_context
|
||
|
|
|
||
|
|
method array :
|
||
|
|
'a.
|
||
|
|
('ctx, 'a, 'res) T.lift_map_with_context ->
|
||
|
|
('ctx, 'a array, 'res) T.lift_map_with_context
|
||
|
|
|
||
|
|
method record : 'ctx -> (string * 'res) list -> 'res
|
||
|
|
method constr : 'ctx -> string -> 'res list -> 'res
|
||
|
|
method tuple : 'ctx -> 'res list -> 'res
|
||
|
|
method float : ('ctx, float, 'res) T.lift_map_with_context
|
||
|
|
method int32 : ('ctx, int32, 'res) T.lift_map_with_context
|
||
|
|
method int64 : ('ctx, int64, 'res) T.lift_map_with_context
|
||
|
|
method nativeint : ('ctx, nativeint, 'res) T.lift_map_with_context
|
||
|
|
method unit : ('ctx, unit, 'res) T.lift_map_with_context
|
||
|
|
|
||
|
|
method option :
|
||
|
|
'a.
|
||
|
|
('ctx, 'a, 'res) T.lift_map_with_context ->
|
||
|
|
('ctx, 'a option, 'res) T.lift_map_with_context
|
||
|
|
|
||
|
|
method list :
|
||
|
|
'a.
|
||
|
|
('ctx, 'a, 'res) T.lift_map_with_context ->
|
||
|
|
('ctx, 'a list, 'res) T.lift_map_with_context
|
||
|
|
end
|