Import Upstream version 20180207
[hcoop/debian/mlton.git] / basis-library / list / list.sml
CommitLineData
7f918cf1
CE
1(* Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
3 * Copyright (C) 1997-2000 NEC Research Institute.
4 *
5 * MLton is released under a BSD-style license.
6 * See the file MLton-LICENSE for details.
7 *)
8
9structure List: LIST =
10 struct
11 open Int
12
13 datatype list = datatype Primitive.List.list
14
15 exception Empty
16
17 val null =
18 fn [] => true
19 | _ => false
20
21 val hd =
22 fn x :: _ => x
23 | _ => raise Empty
24
25 val tl =
26 fn _ :: l => l
27 | _ => raise Empty
28
29 val rec last =
30 fn [] => raise Empty
31 | [x] => x
32 | _ :: l => last l
33
34 val getItem =
35 fn [] => NONE
36 | x :: r => SOME (x, r)
37
38 fun foldl f b l =
39 let
40 fun loop (l, b) =
41 case l of
42 [] => b
43 | x :: l => loop (l, f (x, b))
44 in loop (l, b)
45 end
46
47 fun length l = foldl (fn (_, n) => n +? 1) 0 l
48
49 fun appendRev (l1, l2) = foldl (op ::) l2 l1
50
51 val revAppend = appendRev
52
53 fun rev l = appendRev (l, [])
54
55 fun l1 @ l2 =
56 case l2 of
57 [] => l1
58 | _ => appendRev (rev l1, l2)
59
60 fun foldr f b l = foldl f b (rev l)
61
62 fun concat ls = foldr (op @) [] ls
63
64 fun app f = foldl (f o #1) ()
65
66 fun map f l = rev (foldl (fn (x, l) => f x :: l) [] l)
67
68 fun mapPartial pred l =
69 rev (foldl (fn (x, l) => (case pred x of
70 NONE => l
71 | SOME y => y :: l))
72 [] l)
73
74 fun filter pred = mapPartial (fn x => if pred x then SOME x else NONE)
75
76 fun partition pred l =
77 let
78 val (pos, neg) =
79 foldl (fn (x, (trues, falses)) =>
80 if pred x then (x :: trues, falses)
81 else (trues, x :: falses))
82 ([], []) l
83 in (rev pos, rev neg)
84 end
85
86 fun find pred =
87 let
88 val rec loop =
89 fn [] => NONE
90 | x :: l => if pred x
91 then SOME x
92 else loop l
93 in loop
94 end
95
96 fun exists pred l =
97 case find pred l of
98 NONE => false
99 | SOME _ => true
100
101 fun all pred = not o (exists (not o pred))
102
103 fun tabulate (n, f) =
104 if Primitive.Controls.safe andalso n < 0
105 then raise Size
106 else let
107 fun loop (i, ac) =
108 if i < n
109 then loop (i + 1, f i :: ac)
110 else rev ac
111 in loop (0, [])
112 end
113
114 fun nth (l, n) =
115 let
116 fun loop (l, n) =
117 case l of
118 [] => raise Subscript
119 | x :: l =>
120 if n > 0
121 then loop (l, n - 1)
122 else x
123 in
124 if Primitive.Controls.safe andalso n < 0
125 then raise Subscript
126 else loop (l, n)
127 end
128
129 fun take (l, n) =
130 let
131 fun loop (l, n, ac) =
132 if n > 0
133 then (case l of
134 [] => raise Subscript
135 | x :: l => loop (l, n - 1, x :: ac))
136 else rev ac
137 in
138 if Primitive.Controls.safe andalso n < 0
139 then raise Subscript
140 else loop (l, n, [])
141 end
142
143 fun drop (l, n) =
144 let
145 fun loop (l, n) =
146 if n > 0
147 then (case l of
148 [] => raise Subscript
149 | _ :: l => loop (l, n - 1))
150 else l
151 in
152 if Primitive.Controls.safe andalso n < 0
153 then raise Subscript
154 else loop (l, n)
155 end
156
157 fun collate cmp =
158 let
159 val rec loop =
160 fn ([], []) => EQUAL
161 | ([], _) => LESS
162 | (_, []) => GREATER
163 | (x1::l1,x2::l2) => (case cmp (x1, x2) of
164 EQUAL => loop (l1, l2)
165 | ans => ans)
166 in loop
167 end
168 end
169
170structure ListGlobal: LIST_GLOBAL = List
171open ListGlobal