open! Import open! Sequence let%test_unit "of_lazy" = let t = range 0 100 in [%test_result: int list] (to_list (of_lazy (lazy t))) ~expect:(to_list t) ;; let%test_unit _ = let seq_of_seqs = unfold ~init:0 ~f:(fun i -> Some (unfold ~init:i ~f:(fun j -> Some ((i, j), j + 1)), i + 1)) in [%test_result: (int * int) list] (to_list (take (interleave seq_of_seqs) 10)) ~expect:[ 0, 0; 0, 1; 1, 1; 0, 2; 1, 2; 2, 2; 0, 3; 1, 3; 2, 3; 3, 3 ] ;; let%expect_test "round_robin vs interleave" = let list_of_lists = [ [ 1; 10; 100; 1000 ]; [ 2; 20; 200 ]; [ 3; 30 ]; [ 4 ] ] in let list_of_seqs = List.map list_of_lists ~f:of_list in let seq_of_seqs = of_list list_of_seqs in print_s [%sexp (to_list (round_robin list_of_seqs) : int list)]; [%expect {| (1 2 3 4 10 20 30 100 200 1_000) |}]; print_s [%sexp (to_list (interleave seq_of_seqs) : int list)]; [%expect {| (1 10 2 100 20 3 1_000 200 30 4) |}] ;; let%test_unit _ = let evens = unfold ~init:0 ~f:(fun i -> Some (i, i + 2)) in let vowels = cycle_list_exn [ 'a'; 'e'; 'i'; 'o'; 'u' ] in [%test_result: (int * char) list] (to_list (take (interleaved_cartesian_product evens vowels) 10)) ~expect: [ 0, 'a'; 0, 'e'; 2, 'a'; 0, 'i'; 2, 'e'; 4, 'a'; 0, 'o'; 2, 'i'; 4, 'e'; 6, 'a' ] ;; let%test_module "Sequence.merge*" = (module struct let%test_unit _ = [%test_eq: (int, int) Merge_with_duplicates_element.t list] (to_list (merge_with_duplicates (of_list [ 1; 2 ]) (of_list [ 2; 3 ]) (* Can't use Core_int.compare because it would be a dependency cycle. *) ~compare:Int.compare)) [ Left 1; Both (2, 2); Right 3 ] ;; let%test_unit _ = [%test_eq: (int, int) Merge_with_duplicates_element.t list] (to_list (merge_with_duplicates (of_list [ 2; 1 ]) (of_list [ 2; 3 ]) ~compare:Int.compare)) [ Both (2, 2); Left 1; Right 3 ] ;; let test_merge_semantics ~merge ~(normalize_list : _ -> compare:(_ -> _ -> _) -> _) = Base_quickcheck.Test.run_exn (module struct module Deduped_and_sorted_int_list = struct type t = int list [@@deriving quickcheck, sexp_of] let sort t = normalize_list t ~compare:Int.compare let quickcheck_generator = Base_quickcheck.Generator.map quickcheck_generator ~f:sort ;; let quickcheck_shrinker = Base_quickcheck.Shrinker.map quickcheck_shrinker ~f:sort ~f_inverse:sort ;; end type t = Deduped_and_sorted_int_list.t * Deduped_and_sorted_int_list.t [@@deriving quickcheck, sexp_of] end) ~f:(fun (xs, ys) -> [%test_result: int list] (Sequence.to_list (merge (Sequence.of_list xs) (Sequence.of_list ys) ~compare:Int.compare)) ~expect:(normalize_list (xs @ ys) ~compare:Int.compare)) ;; let%test_unit "merge_deduped_and_sorted" = test_merge_semantics ~merge:Sequence.merge_deduped_and_sorted ~normalize_list:List.dedup_and_sort ;; let%test_unit "merge_sorted" = test_merge_semantics ~merge:Sequence.merge_sorted ~normalize_list:List.sort ;; end) ;; let%test _ = fold ~f:( + ) ~init:0 (of_list [ 1; 2; 3; 4; 5 ]) = 15 let%test _ = fold ~f:( + ) ~init:0 (of_list []) = 0 let%test_unit _ = let test_equal l = [%test_result: int list] (to_list (of_list l)) ~expect:l in test_equal []; test_equal [ 1; 2; 3; 4; 5 ] ;; (* The test for longer list is after range *) let%test_unit _ = [%test_result: int list] (to_list (range 0 5)) ~expect:[ 0; 1; 2; 3; 4 ] let%test_unit _ = [%test_result: int list] (to_list (range ~stop:`inclusive 0 5)) ~expect:[ 0; 1; 2; 3; 4; 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (range ~start:`exclusive 0 5)) ~expect:[ 1; 2; 3; 4 ] ;; let%test_unit _ = [%test_result: int list] (to_list (range ~stride:(-2) 5 1)) ~expect:[ 5; 3 ] ;; (* Test for to_list *) let%test_unit _ = [%test_result: int list] (to_list (range 0 5000)) ~expect:(List.range 0 5000) ;; (* Functions used for testing by comparing to List implementation*) let test_to_list s f g = [%test_result: int list] (to_list (f s)) ~expect:(g (to_list s)) (* For testing, we create a sequence which is equal to 1;2;3;4;5, but with a more interesting structure inside*) let s12345 = map ~f:(fun x -> x / 2) (filter ~f:(fun x -> x % 2 = 0) (of_list [ 1; 2; 3; 4; 5; 6; 7; 8; 9; 10 ])) ;; let sempty = filter ~f:(fun x -> x < 0) (of_list [ 1; 2; 3; 4 ]) let test f g = test_to_list s12345 f g; test_to_list sempty f g ;; let%test_unit _ = [%test_result: int list] (to_list s12345) ~expect:[ 1; 2; 3; 4; 5 ]; [%test_result: int list] (to_list sempty) ~expect:[] ;; let%test_unit _ = [%test_result: int list] (to_list (unfold_with s12345 ~init:1 ~f:(fun s _ -> if s % 2 = 0 then Skip { state = s + 1 } else if s = 5 then Done else Yield { value = s; state = s + 1 }))) ~expect:[ 1; 3 ] ;; let test_delay init = unfold_with_and_finish ~init ~running_step:(fun prev next -> Yield { value = prev; state = next }) ~inner_finished:(fun x -> Some x) ~finishing_step:(fun prev -> match prev with | None -> Done | Some prev -> Yield { value = prev; state = None }) ;; let%test_unit _ = [%test_result: int list] (to_list (test_delay 0 s12345)) ~expect:[ 0; 1; 2; 3; 4; 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (test_delay 0 sempty)) ~expect:[ 0 ] let%test_unit _ = [%test_result: int list] (to_list s12345) ~expect:[ 1; 2; 3; 4; 5 ] let%test_unit _ = test (map ~f:(fun i -> -i)) (List.map ~f:(fun i -> -i)) let%test_unit _ = test (mapi ~f:(fun i j -> j - (2 * i))) (List.mapi ~f:(fun i j -> j - (2 * i))) ;; let%test_unit _ = test (filter ~f:(fun i -> i % 2 = 0)) (List.filter ~f:(fun i -> i % 2 = 0)) ;; let%test _ = length s12345 = 5 && length sempty = 0 let%test_unit _ = [%test_result: int option] (find s12345 ~f:(fun x -> x = 3)) ~expect:(Some 3); [%test_result: int option] (find s12345 ~f:(fun x -> x = 7)) ~expect:None ;; let%test_unit _ = [%test_result: string option] (find_map s12345 ~f:(fun x -> if x = 3 then Some "a" else None)) ~expect:(Some "a"); [%test_result: string option] (find_map s12345 ~f:(fun x -> if x = 7 then Some "a" else None)) ~expect:None ;; let%test_unit _ = [%test_result: string option] (find_mapi s12345 ~f:(fun _ x -> if x = 3 then Some "a" else None)) ~expect:(Some "a") ;; let%test_unit _ = [%test_result: string option] (find_mapi s12345 ~f:(fun _ x -> if x = 7 then Some "a" else None)) ~expect:None ;; let%test_unit _ = [%test_result: (int * int) option] (find_mapi s12345 ~f:(fun i x -> if i + x >= 6 then Some (i, x) else None)) ~expect:(Some (3, 4)) ;; let%test _ = for_all sempty ~f:(fun _ -> false) let%test _ = for_all s12345 ~f:(fun x -> x > 0) let%test _ = not (for_all s12345 ~f:(fun x -> x < 5)) let%test _ = for_alli sempty ~f:(fun _ _ -> false) let%test _ = for_alli s12345 ~f:(fun _ x -> x > 0) let%test _ = not (for_alli s12345 ~f:(fun _ x -> x < 5)) let%test _ = for_alli s12345 ~f:(fun i x -> x = i + 1) let%test _ = not (exists sempty ~f:(fun _ -> assert false)) let%test _ = exists s12345 ~f:(fun x -> x = 5) let%test _ = not (exists s12345 ~f:(fun x -> x = 0)) let%test _ = not (existsi sempty ~f:(fun _ _ -> assert false)) let%test _ = existsi s12345 ~f:(fun _ x -> x = 5) let%test _ = not (existsi s12345 ~f:(fun _ x -> x = 0)) let%test _ = not (existsi s12345 ~f:(fun i x -> x <> i + 1)) let%test_unit _ = let l = ref [] in iter s12345 ~f:(fun x -> l := x :: !l); [%test_result: int list] !l ~expect:[ 5; 4; 3; 2; 1 ] ;; let%test _ = is_empty sempty let%test _ = not (is_empty (of_list [ 1 ])) let%test _ = mem s12345 1 ~equal:Int.equal let%test _ = not (mem s12345 6 ~equal:Int.equal) let%test_unit _ = [%test_result: int list] (to_list empty) ~expect:[] let%test_unit _ = [%test_result: int list] (to_list (bind sempty ~f:(fun _ -> s12345))) ~expect:[] ;; let%test_unit _ = [%test_result: int list] (to_list (bind s12345 ~f:(fun _ -> sempty))) ~expect:[] ;; let%test_unit _ = [%test_result: int list] (to_list (bind s12345 ~f:(fun x -> of_list [ x; -x ]))) ~expect:[ 1; -1; 2; -2; 3; -3; 4; -4; 5; -5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (return 1)) ~expect:[ 1 ] let%test_unit _ = [%test_result: int option] (nth s12345 3) ~expect:(Some 4) let%test_unit _ = [%test_result: int option] (nth s12345 5) ~expect:None let%test_unit _ = [%test_result: int option] (hd s12345) ~expect:(Some 1) let%test_unit _ = [%test_result: int option] (hd sempty) ~expect:None let%test_unit _ = [%test_result: int t option] (tl sempty) ~expect:None let%test_unit _ = match tl s12345 with | Some l -> [%test_result: int list] (to_list l) ~expect:[ 2; 3; 4; 5 ] | None -> failwith "expected Some" ;; let%test_unit _ = [%test_result: (int * int t) option] (next sempty) ~expect:None let%test_unit _ = match next s12345 with | Some (hd, tl) -> [%test_result: int] hd ~expect:1; [%test_result: int list] (to_list tl) ~expect:[ 2; 3; 4; 5 ] | None -> failwith "expected Some" ;; let%test_unit _ = [%test_result: int list] (to_list (filter_opt (of_list [ None; Some 1; None; Some 2; Some 3 ]))) ~expect:[ 1; 2; 3 ] ;; let%test_unit _ = let l, r = split_n s12345 2 in [%test_result: int list] l ~expect:[ 1; 2 ]; [%test_result: int list] (to_list r) ~expect:[ 3; 4; 5 ] ;; let%test_unit _ = [%test_result: int list list] (to_list (chunks_exn s12345 2)) ~expect:[ [ 1; 2 ]; [ 3; 4 ]; [ 5 ] ] ;; let%test_unit _ = [%test_result: int list] (to_list (append s12345 s12345)) ~expect:[ 1; 2; 3; 4; 5; 1; 2; 3; 4; 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (append sempty s12345)) ~expect:[ 1; 2; 3; 4; 5 ] ;; let%test_unit _ = [%test_result: (int * int) list] (to_list (zip s12345 sempty)) ~expect:[] ;; let%test_unit _ = [%test_result: (int * int) list] (to_list (zip s12345 (of_list [ 6; 5; 4; 3; 2; 1 ]))) ~expect:[ 1, 6; 2, 5; 3, 4; 4, 3; 5, 2 ] ;; let%test_unit _ = [%test_result: (int * string) list] (to_list (zip s12345 (of_list [ "a" ]))) ~expect:[ 1, "a" ] ;; let%test_unit _ = [%test_result: (int * int) option] (find_consecutive_duplicate s12345 ~equal:( = )) ~expect:None ;; let%test_unit _ = [%test_result: (int * int) option] (find_consecutive_duplicate (of_list [ 1; 2; 2; 3; 4; 4; 5 ]) ~equal:( = )) ~expect:(Some (2, 2)) ;; let%test_unit _ = [%test_result: int list] (to_list (remove_consecutive_duplicates ~equal:( = ) (of_list [ 1; 2; 2; 3; 3; 3; 3; 4; 4; 5; 6; 6; 7 ]))) ~expect:[ 1; 2; 3; 4; 5; 6; 7 ] ;; let%test_unit _ = [%test_result: int list] (to_list (remove_consecutive_duplicates ~equal:( = ) s12345)) ~expect:[ 1; 2; 3; 4; 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (remove_consecutive_duplicates ~equal:(fun _ _ -> true) s12345)) ~expect:[ 1 ] ;; let%test_unit _ = [%test_result: int list] (to_list (init (-1) ~f:(fun _ -> assert false))) ~expect:[] ;; let%test_unit _ = [%test_result: int list] (to_list (init 5 ~f:Fn.id)) ~expect:[ 0; 1; 2; 3; 4 ] ;; let%test_unit _ = [%test_result: int list] (to_list (sub s12345 ~pos:4 ~len:10)) ~expect:[ 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (sub s12345 ~pos:1 ~len:2)) ~expect:[ 2; 3 ] ;; let%test_unit _ = [%test_result: int list] (to_list (sub s12345 ~pos:0 ~len:0)) ~expect:[] let%test_unit _ = [%test_result: int list] (to_list (take s12345 2)) ~expect:[ 1; 2 ] let%test_unit _ = [%test_result: int list] (to_list (take s12345 0)) ~expect:[] let%test_unit _ = [%test_result: int list] (to_list (take s12345 9)) ~expect:[ 1; 2; 3; 4; 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (drop s12345 2)) ~expect:[ 3; 4; 5 ] let%test_unit _ = [%test_result: int list] (to_list (drop s12345 0)) ~expect:[ 1; 2; 3; 4; 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (drop s12345 9)) ~expect:[] let%test_unit _ = [%test_result: int list] (to_list (take_while ~f:(fun x -> x < 3) s12345)) ~expect:[ 1; 2 ] ;; let%test_unit _ = [%test_result: int list] (to_list (drop_while ~f:(fun x -> x < 3) s12345)) ~expect:[ 3; 4; 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (shift_right (shift_right s12345 0) (-1))) ~expect:[ -1; 0; 1; 2; 3; 4; 5 ] ;; let%test_unit _ = [%test_result: char list] (to_list (intersperse ~sep:'a' (of_list []))) ~expect:[] ;; let%test_unit _ = [%test_result: char list] (to_list (intersperse ~sep:'a' (of_list [ 'b' ]))) ~expect:[ 'b' ] ;; let%test_unit _ = [%test_result: int list] (to_list (intersperse ~sep:(-1) (take s12345 1))) ~expect:[ 1 ] ;; let%test_unit _ = [%test_result: int list] (to_list (intersperse ~sep:0 s12345)) ~expect:[ 1; 0; 2; 0; 3; 0; 4; 0; 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (take (repeat 1) 3)) ~expect:[ 1; 1; 1 ] ;; let%test_unit _ = [%test_result: int list] (to_list (take (cycle_list_exn [ 1; 2; 3; 4; 5 ]) 7)) ~expect:[ 1; 2; 3; 4; 5; 1; 2 ] ;; let%expect_test _ = require_does_raise [%here] (fun () -> cycle_list_exn []); [%expect {| (Invalid_argument Sequence.cycle_list_exn) |}] ;; let%test_unit _ = [%test_result: (char * int) list] (to_list (cartesian_product (of_list [ 'a'; 'b' ]) s12345)) ~expect: [ 'a', 1; 'a', 2; 'a', 3; 'a', 4; 'a', 5; 'b', 1; 'b', 2; 'b', 3; 'b', 4; 'b', 5 ] ;; let%test_unit _ = [%test_result: float] (delayed_fold s12345 ~init:0.0 ~f:(fun a i ~k -> if Float.( <= ) a 5.0 then k (a +. Float.of_int i) else a) ~finish:(fun _ -> assert false)) ~expect:6.0 ;; let%expect_test "fold_m" = let module Simple_monad = struct type 'a t = | Return of 'a | Step of 'a t [@@deriving sexp_of] let return a = Return a let rec bind t ~f = match t with | Return a -> f a | Step t -> Step (bind t ~f) ;; let step = Step (Return ()) end in fold_m ~bind:Simple_monad.bind ~return:Simple_monad.return s12345 ~init:[] ~f:(fun acc n -> Simple_monad.bind Simple_monad.step ~f:(fun () -> Simple_monad.return (n :: acc))) |> printf !"%{sexp: int list Simple_monad.t}\n"; [%expect {| (Step (Step (Step (Step (Step (Return (5 4 3 2 1))))))) |}] ;; let%expect_test "iter_m" = iter_m ~bind:Generator.bind ~return:Generator.return s12345 ~f:Generator.yield |> Generator.run |> printf !"%{sexp: int t}\n"; [%expect {| (1 2 3 4 5) |}] ;; let%test _ = let num_computations = ref 0 in let t = memoize (unfold ~init:() ~f:(fun () -> Int.incr num_computations; None)) in iter t ~f:Fn.id; iter t ~f:Fn.id; !num_computations = 1 ;; let%test_unit _ = [%test_result: int list] (to_list (drop_eagerly s12345 0)) ~expect:[ 1; 2; 3; 4; 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (drop_eagerly s12345 2)) ~expect:[ 3; 4; 5 ] ;; let%test_unit _ = [%test_result: int list] (to_list (drop_eagerly s12345 5)) ~expect:[] let%test_unit _ = [%test_result: int list] (to_list (drop_eagerly s12345 8)) ~expect:[] let compare_tests = [ [ 1; 2; 3 ], [ 1; 2; 3 ], 0 ; [ 1; 2; 3 ], [], 1 ; [], [ 1; 2; 3 ], -1 ; [ 1; 2 ], [ 1; 2; 3 ], -1 ; [ 1; 2; 3 ], [ 1; 2 ], 1 ; [ 1; 3; 2 ], [ 1; 2; 3 ], 1 ; [ 1; 2; 3 ], [ 1; 3; 2 ], -1 ] ;; (* this test has to use base OCaml library functions to avoid circular dependencies *) let%test _ = List.for_all ~f:Fn.id (List.map ~f:(fun (l1, l2, expected_res) -> compare Int.compare (of_list l1) (of_list l2) = expected_res) compare_tests) ;; let%expect_test "[equal]" = let equal l1 l2 = let t1 = of_list l1 in let t2 = of_list l2 in let b = equal Int.equal t1 t2 in print_s [%sexp (b : bool)]; require [%here] (Bool.equal b (equal Int.equal t2 t1)) in equal [] []; [%expect {| true |}]; equal [] [ 1 ]; [%expect {| false |}]; equal [ 1 ] [ 1 ]; [%expect {| true |}]; equal [ 1 ] [ 1; 2 ]; [%expect {| false |}] ;; let%test_unit "[equal] randomised test" = let with_gen ?examples gen = Base_quickcheck.Test.run_exn ?examples (module struct type t = int list * int list [@@deriving quickcheck, sexp_of] let quickcheck_generator = gen end) ~f:(fun (left, right) -> [%test_result: bool] ~expect:(List.equal Int.equal left right) (Comparable.lift (Sequence.equal Int.equal) ~f:Sequence.of_list left right)) in let list_gen = [%generator: int list] in (* certainly equal. *) with_gen ~examples: (List.map ~f:(fun x -> x, x) [ []; [ 1 ]; [ Int.max_value ]; [ 5; 4; 3; 2; 1 ] ]) (Base_quickcheck.Generator.map list_gen ~f:(fun x -> x, x)); (* Probably not equal. *) with_gen ~examples:[ [], []; [], [ 1 ]; [ 1 ], []; [ Int.min_value ], [ Int.max_value ] ] (Base_quickcheck.Generator.both list_gen list_gen) ;; let%test_unit _ = [%test_result: int list] (folding_map (of_list [ 1; 2; 3; 4 ]) ~init:0 ~f:(fun acc x -> let y = acc + x in y, y) |> to_list) ~expect:[ 1; 3; 6; 10 ] ;; let%test_unit _ = [%test_result: bool] (folding_map empty ~init:0 ~f:(fun acc x -> let y = acc + x in y, y) |> is_empty) ~expect:true ;; let%test_unit _ = [%test_result: int list] (folding_mapi (of_list [ 1; 2; 3; 4 ]) ~init:0 ~f:(fun i acc x -> let y = acc + (i * x) in y, y) |> to_list) ~expect:[ 0; 2; 8; 20 ] ;; let%test_unit _ = [%test_result: bool] (folding_mapi empty ~init:0 ~f:(fun i acc x -> let y = acc + (i * x) in y, y) |> is_empty) ~expect:true ;; let%expect_test "findi" = Base_quickcheck.Test.run_exn (module struct type t = int option list * (int -> int -> bool) [@@deriving quickcheck, sexp_of] end) ~f:(fun (option_list, f) -> let sequence = option_list |> of_list |> filter_opt in [%test_result: (int * int) option] (findi sequence ~f) ~expect:(List.findi (to_list sequence) ~f)); [%expect {| |}] ;; let%expect_test _ = let xs = init 3 ~f:Fn.id |> Generator.of_sequence in let ( @ ) xs ys = Generator.bind xs ~f:(fun () -> ys) in xs @ xs @ xs @ xs @ xs |> Generator.run |> [%sexp_of: int t] |> print_s; [%expect {| (0 1 2 0 1 2 0 1 2 0 1 2 0 1 2) |}] ;; let%test_module "group" = (module struct let%test _ = of_list [ 1; 2; 3; 4 ] |> group ~break:(fun _ x -> Int.equal x 3) |> [%compare.equal: int list t] (of_list [ [ 1; 2 ]; [ 3; 4 ] ]) ;; let%test _ = group empty ~break:(fun _ -> assert false) |> [%compare.equal: unit list t] empty ;; let mis = of_list [ 'M'; 'i'; 's'; 's'; 'i'; 's'; 's'; 'i'; 'p'; 'p'; 'i' ] let equal_letters = of_list [ [ 'M' ] ; [ 'i' ] ; [ 's'; 's' ] ; [ 'i' ] ; [ 's'; 's' ] ; [ 'i' ] ; [ 'p'; 'p' ] ; [ 'i' ] ] ;; let single_letters = of_list [ [ 'M'; 'i'; 's'; 's'; 'i'; 's'; 's'; 'i'; 'p'; 'p'; 'i' ] ] ;; let%test _ = group ~break:Char.( <> ) mis |> [%compare.equal: char list t] equal_letters ;; let%test _ = group ~break:(fun _ _ -> false) mis |> [%compare.equal: char list t] single_letters ;; end) ;; let%test_module "Caml.Seq" = (module struct let list = [ 1; 2; 3; 4 ] let%expect_test "of_seq" = list |> Stdlib.List.to_seq |> Sequence.of_seq |> Sequence.iter ~f:(printf "%d\n"); [%expect {| 1 2 3 4 |}] ;; let%expect_test "to_seq" = list |> Sequence.of_list |> Sequence.to_seq |> Stdlib.Seq.iter (printf "%d\n"); [%expect {| 1 2 3 4 |}] ;; end) ;;