let create ~fold ?length ?is_empty ?iter ?exists ?for_all ?find ?to_list ?to_array
    () =
  let fold = fold.f in
  let iter' t ~f = fold t ~init:() ~f:(fun () a -> f a) in
  (* like Option.value, but avoids cyclic dependency *)
  let uw opt default = match opt with None -> default | Some x -> x in
  let iter = uw iter iter' in
  let length' c = fold c ~init:0 ~f:(fun acc _ -> acc + 1) in
  let is_empty' c =
    with_return (fun r ->
      iter c ~f:(fun _ -> r.return false);
      true)
  in
  let exists' c ~f =
    with_return (fun r ->
      iter c ~f:(fun x -> if f x then r.return true);
      false)
  in
  let for_all' c ~f =
    with_return (fun r ->
      iter c ~f:(fun x -> if not (f x) then r.return false);
      true)
  in
  let find' c ~f =
    with_return (fun r ->
      iter c ~f:(fun x -> if f x then r.return (Some x));
      None)
  in
  let to_list' c =
    List.rev (fold c ~init:[] ~f:(fun acc x -> x :: acc))
  in
  let to_array' c = Array.of_list (to_list' c) in
  { iter     = iter;
    fold     = fold;
    length   = uw length   length'  ;
    is_empty = uw is_empty is_empty';
    exists   = uw exists   exists'  ;
    for_all  = uw for_all  for_all' ;
    find     = uw find     find'    ;
    to_list  = uw to_list  to_list' ;
    to_array = uw to_array to_array';
  }