open! Import module type S = Indexed_container.S1 with type 'a t = 'a list module This_list : S = struct include List include Indexed_container.Make (struct type 'a t = 'a list let fold = List.fold let iter = `Custom List.iter let length = `Custom List.length let foldi = `Define_using_fold let iteri = `Define_using_fold end) end module That_list : S = List let examples = [ []; [ 1 ]; [ 2; 3 ]; [ 4; 5; 1 ]; List.init 8 ~f:(fun i -> i * i) ] module type Output = sig type t [@@deriving compare, sexp_of] end module Int_list = struct type t = int list [@@deriving compare, sexp_of] end module Int_pair_option = struct type t = (int * int) option [@@deriving compare, sexp_of] end module Int_option = struct type t = int option [@@deriving compare, sexp_of] end let check (type a) here examples ~actual ~expect (module Output : Output with type t = a) = List.iter examples ~f:(fun example -> let actual = actual example in let expect = expect example in require here (Output.compare actual expect = 0) ~if_false_then_print_s:(lazy [%message (expect : Output.t)]); print_s [%sexp (actual : Output.t)]) ;; let%expect_test "foldi" = let f i acc elt = if i % 2 = 0 then elt :: acc else acc in check [%here] examples (module Int_list) ~actual:(fun list -> This_list.foldi list ~init:[] ~f) ~expect:(fun list -> That_list.foldi list ~init:[] ~f); [%expect {| () (1) (2) (1 4) (36 16 4 0) |}] ;; let%expect_test "findi" = let check f = check [%here] examples (module Int_pair_option) ~actual:(fun list -> This_list.findi list ~f) ~expect:(fun list -> That_list.findi list ~f) in check (fun i _elt -> i = 0); [%expect {| () ((0 1)) ((0 2)) ((0 4)) ((0 0)) |}]; check (fun _i elt -> elt = 1); [%expect {| () ((0 1)) () ((2 1)) ((1 1)) |}] ;; let%expect_test "find_mapi" = let f i elt = if elt = 1 then Some ((i * 100) + elt) else None in check [%here] examples (module Int_option) ~actual:(fun list -> This_list.find_mapi list ~f) ~expect:(fun list -> That_list.find_mapi list ~f); [%expect {| () (1) () (201) (101) |}] ;; let%expect_test "iteri" = let go iteri = let acc = ref [] in iteri ~f:(fun i elt -> acc := i :: elt :: !acc); !acc in check [%here] examples (module Int_list) ~actual:(fun list -> go (This_list.iteri list)) ~expect:(fun list -> go (That_list.iteri list)); [%expect {| () (0 1) (1 3 0 2) (2 1 1 5 0 4) (7 49 6 36 5 25 4 16 3 9 2 4 1 1 0 0) |}] ;; let bool_examples = [ [] ; [ true ] ; [ false ] ; [ false; false ] ; [ true; false ] ; [ false; true ] ; [ true; true ] ] ;; let%expect_test "for_alli" = let f _i elt = elt in check [%here] bool_examples (module Bool) ~actual:(fun list -> This_list.for_alli list ~f) ~expect:(fun list -> That_list.for_alli list ~f); [%expect {| true true false false false false true |}] ;; let%expect_test "existsi" = let f _i elt = elt in check [%here] bool_examples (module Bool) ~actual:(fun list -> This_list.existsi list ~f) ~expect:(fun list -> That_list.existsi list ~f); [%expect {| false true false false true true true |}] ;; let%expect_test "counti" = let f _i elt = elt in check [%here] bool_examples (module Int) ~actual:(fun list -> This_list.counti list ~f) ~expect:(fun list -> That_list.counti list ~f); [%expect {| 0 1 0 0 1 1 2 |}] ;;