Source file nonempty_list.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
open! Stdppx
module List = List_with_helpers
include Nonempty_list_type.Nonempty_list
let hd (hd :: _) = hd
let tl (_ :: tl) = tl
let to_list (hd :: tl) : _ list = hd :: tl
let of_list = function
| [] -> None
| hd :: tl -> Some (hd :: tl)
;;
let of_list_exn ~(here : [%call_pos]) = function
| [] ->
Location.raise_errorf
~loc:{ loc_ghost = false; loc_start = here; loc_end = here }
"Nonempty_list.of_list_exn: empty list"
| hd :: tl -> hd :: tl
;;
let sexp_of_t f t = sexp_of_list f (to_list t)
let create hd tl = hd :: tl
let singleton x = [ x ]
let cons x t = x :: to_list t
let length (_ :: tl) = 1 + List.length tl
let map (hd :: tl) ~f = f hd :: List.map tl ~f
let mapi (hd :: tl) ~f = f 0 hd :: List.mapi tl ~f:(fun i x -> f (i + 1) x)
let compare (x :: xs) (y :: ys) ~cmp =
match cmp x y with
| 0 -> List.compare ~cmp xs ys
| r -> r
;;
let sort_uniq t ~cmp = t |> to_list |> List.sort_uniq ~cmp |> of_list_exn
let stable_dedup t ~cmp = t |> to_list |> List.stable_dedup ~cmp |> of_list_exn
let[@tail_mod_cons] rec concat_map_list xs ~f =
match xs with
| [] -> []
| x :: xs ->
let (y :: ys) = f x in
y :: append_and_concat_map_list ys xs ~f
and[@tail_mod_cons] append_and_concat_map_list ys xs ~f =
match ys with
| [] -> concat_map_list xs ~f
| y :: ys -> y :: append_and_concat_map_list ys xs ~f
;;
let[@tail_mod_cons] concat_map (x :: xs) ~f =
let (y :: ys) = f x in
y :: append_and_concat_map_list ys xs ~f
;;
let concat t = concat_map t ~f:Fn.id
let rev (hd :: tl) =
let hd, tl = List.fold_left tl ~init:(hd, []) ~f:(fun (hd, tl) elt -> elt, hd :: tl) in
hd :: tl
;;
let product outer =
let (inner :: outer) = rev outer in
List.fold_left
outer
~init:(map inner ~f:(fun x -> [ x ]))
~f:(fun acc inner ->
concat_map inner ~f:(fun hd -> map acc ~f:(fun tl -> cons hd tl)))
;;
module Or_first_error = struct
let fold_left t ~init ~f = List.Or_first_error.fold_left (to_list t) ~init ~f
let map (x :: xs) ~f =
Result.bind (f x) ~f:(fun y ->
Result.map (List.Or_first_error.map ~f xs) ~f:(fun ys -> y :: ys))
;;
let concat_map t ~f = map t ~f |> Result.map ~f:concat
end