mte/unikernel/duniverse/base/test/test_map_traversal.ml
2025-11-11 02:07:51 +01:00

156 lines
4 KiB
OCaml

open! Import
open! Map
open! Int
module Lazy_apply = struct
module T = struct
type 'a t = { compute : unit -> 'a } [@@unboxed]
let run t = t.compute ()
let return x = { compute = (fun () -> x) }
let map x ~f = { compute = (fun () -> f (run x)) }
let both x y = { compute = (fun () -> run x, run y) }
let map2 a b ~f = map (both a b) ~f:(fun (x, y) -> f x y)
let map = `Custom map
end
include T
include Applicative.Make_using_map2 (T)
let of_thunk f = { compute = (fun () -> run (f ())) }
end
module Lazy_map = Map.Make_applicative_traversals (Lazy_apply)
let%expect_test "mapi correctness check" =
let map = Map.of_alist_exn (module Int) (List.init 100 ~f:(fun x -> x, x)) in
let f ~key:_ ~data = data + 1 in
let test_output =
Lazy_map.mapi map ~f:(fun ~key ~data -> Lazy_apply.return (f ~key ~data))
|> Lazy_apply.run
in
let reference_output = Map.mapi map ~f in
require [%here] (Map.equal Int.equal test_output reference_output);
require [%here] (Map.invariants test_output);
[%expect {| |}]
;;
let%expect_test "filter_mapi correctness check" =
let map = Map.of_alist_exn (module Int) (List.init 1000 ~f:(fun x -> x, x)) in
let f ~key:_ ~data = if data % 50 > 10 then None else Some data in
let test_output =
Lazy_map.filter_mapi map ~f:(fun ~key ~data -> Lazy_apply.return (f ~key ~data))
|> Lazy_apply.run
in
let reference_output = Map.filter_mapi map ~f in
require [%here] (Map.equal Int.equal test_output reference_output);
require [%here] (Map.invariants test_output);
[%expect {| |}]
;;
module Step_applicative = struct
module M = struct
type 'a t = { compute : steps:int -> ('a * int, 'a t) Either.t }
let return x = { compute = (fun ~steps -> First (x, steps)) }
let step x =
let rec t =
{ compute = (fun ~steps -> if steps > 0 then First (x, steps - 1) else Second t) }
in
t
;;
let internal_map x ~f =
let rec fn t =
{ compute =
(fun ~steps ->
match t.compute ~steps with
| First (x, steps) -> First (f x, steps)
| Second t -> Second (fn t))
}
in
fn x
;;
let map2 a b ~f =
let rec fn a =
{ compute =
(fun ~steps ->
match a.compute ~steps with
| First (x, steps) -> (internal_map b ~f:(fun y -> f x y)).compute ~steps
| Second t -> Second (fn t))
}
in
fn a
;;
let map = `Custom internal_map
let of_thunk f =
{ compute =
(fun ~steps ->
let t = f () in
t.compute ~steps)
}
;;
end
include M
include Applicative.Make_using_map2 (M)
end
module Step_map = Map.Make_applicative_traversals (Step_applicative)
let%expect_test "mapi lazy check" =
let map = Map.of_alist_exn (module Int) (List.init 10 ~f:(fun x -> x, x)) in
let f ~key:_ ~data = data * 2 in
(* transform the map, expect no output yet *)
let step_computation =
Step_map.mapi map ~f:(fun ~key ~data ->
Step_applicative.of_thunk (fun () ->
print_s [%message (key : int) (data : int)];
Step_applicative.step (f ~key ~data)))
in
[%expect {| |}];
(* take a few steps, expect some but not all output *)
let more_computation =
match step_computation.compute ~steps:3 with
| First _ -> assert false
| Second c -> c
in
[%expect
{|
((key 0)
(data 0))
((key 1)
(data 1))
((key 2)
(data 2))
((key 3)
(data 3))
|}];
(* take more than enough steps to finish, expect the rest of the output *)
let test_output =
match more_computation.compute ~steps:100 with
| First (r, _) -> r
| Second _ -> assert false
in
let reference_output = Map.mapi map ~f in
require [%here] (Map.equal Int.equal test_output reference_output);
[%expect
{|
((key 4)
(data 4))
((key 5)
(data 5))
((key 6)
(data 6))
((key 7)
(data 7))
((key 8)
(data 8))
((key 9)
(data 9))
|}]
;;