Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh |
2 | * Jagannathan, and Stephen Weeks. | |
3 | * | |
4 | * MLton is released under a BSD-style license. | |
5 | * See the file MLton-LICENSE for details. | |
6 | *) | |
7 | ||
8 | structure LinkedList: LINKED_LIST = | |
9 | struct | |
10 | ||
11 | structure Node = | |
12 | struct | |
13 | datatype 'a t = T of {elt: 'a, | |
14 | next: 'a t option ref} | |
15 | ||
16 | fun new elt = T {elt = elt, | |
17 | next = ref NONE} | |
18 | ||
19 | fun cons (elt, next) = T {elt = elt, | |
20 | next = ref (SOME next)} | |
21 | ||
22 | fun clearNext (T {next, ...}) = next := NONE | |
23 | fun setNext (T {next, ...}, n) = next := SOME n | |
24 | ||
25 | fun fold (n, ac, f) = | |
26 | let | |
27 | fun loop (T {elt, next}, ac) = | |
28 | let | |
29 | val ac = f (elt, ac) | |
30 | in | |
31 | case !next of | |
32 | NONE => ac | |
33 | | SOME n => loop (n, ac) | |
34 | end | |
35 | in | |
36 | loop (n, ac) | |
37 | end | |
38 | end | |
39 | ||
40 | datatype 'a t = T of {first: 'a Node.t option ref, | |
41 | last: 'a Node.t option ref} | |
42 | ||
43 | fun invariant (T {first, last}) = | |
44 | case (!first, !last) of | |
45 | (NONE, NONE) => true | |
46 | | (SOME _, SOME (Node.T {next, ...})) => not (isSome (!next)) | |
47 | | _ => false | |
48 | ||
49 | fun fold (T {first, ...}, ac, f) = | |
50 | case !first of | |
51 | NONE => ac | |
52 | | SOME n => Node.fold (n, ac, f) | |
53 | ||
54 | fun toList l = rev (fold (l, [], op ::)) | |
55 | ||
56 | fun layout layoutX l = List.layout layoutX (toList l) | |
57 | ||
58 | fun empty () = T {first = ref NONE, | |
59 | last = ref NONE} | |
60 | ||
61 | fun splice (T {first = f, last = l}, T {first = f', last = l'}): unit = | |
62 | case (!l, !f') of | |
63 | (NONE, NONE) => () | |
64 | | (NONE, _) => (f := !f'; l := !l') | |
65 | | (_, NONE) => () | |
66 | | (SOME ln, SOME f'n) => | |
67 | (Node.setNext (ln, f'n) | |
68 | ; l := !l') | |
69 | ||
70 | val ('a, 'b) unfoldr: 'a * ('a -> ('b * 'a) option) -> 'b t = | |
71 | fn (a, f) => | |
72 | case f a of | |
73 | NONE => empty () | |
74 | | SOME (b, a) => | |
75 | let | |
76 | val last = Node.new b | |
77 | fun loop (a: 'a, n: 'b Node.t): 'b Node.t = | |
78 | case f a of | |
79 | NONE => n | |
80 | | SOME (b, a) => loop (a, Node.cons (b, n)) | |
81 | val first = loop (a, last) | |
82 | in | |
83 | T {first = ref (SOME first), | |
84 | last = ref (SOME last)} | |
85 | end | |
86 | ||
87 | val unfoldri: int * 'a * (int * 'a -> 'b * 'a) -> 'b t = | |
88 | fn (n, a, f) => | |
89 | if n < 0 | |
90 | then Error.bug "LinkedList.unfoldri" | |
91 | else | |
92 | unfoldr ((n - 1, a), fn (i, a) => | |
93 | if i < 0 | |
94 | then NONE | |
95 | else let | |
96 | val (b, a) = f (i, a) | |
97 | in | |
98 | SOME (b, (i - 1, a)) | |
99 | end) | |
100 | ||
101 | val ('a, 'b) unfold: 'a * ('a -> ('b * 'a) option) -> 'b t = | |
102 | fn (a, f) => | |
103 | case f a of | |
104 | NONE => empty () | |
105 | | SOME (b, a) => | |
106 | let | |
107 | val first = Node.new b | |
108 | fun loop (a: 'a, n: 'b Node.t): 'b Node.t = | |
109 | case f a of | |
110 | NONE => n | |
111 | | SOME (b, a) => | |
112 | let | |
113 | val n' = Node.new b | |
114 | val _ = Node.setNext (n, n') | |
115 | in | |
116 | loop (a, n') | |
117 | end | |
118 | val last = loop (a, first) | |
119 | in | |
120 | T {first = ref (SOME first), | |
121 | last = ref (SOME last)} | |
122 | end | |
123 | ||
124 | val unfoldi: int * 'a * (int * 'a -> 'b * 'a) -> 'b t = | |
125 | fn (n, a, f) => | |
126 | if n < 0 | |
127 | then Error.bug "LinkedList.unfoldi" | |
128 | else | |
129 | unfold ((0, a), fn (i, a) => | |
130 | if i >= n | |
131 | then NONE | |
132 | else let | |
133 | val (b, a') = f (i, a) | |
134 | in | |
135 | SOME (b, (i + 1, a')) | |
136 | end) | |
137 | ||
138 | fun reverse (ll as T {first, last}) = | |
139 | (if invariant ll | |
140 | then () | |
141 | else Out.output (Out.error, "reverse 1\n") | |
142 | ; | |
143 | case !first of | |
144 | NONE => () | |
145 | | SOME (n as Node.T {next, ...}) => | |
146 | case !next of | |
147 | NONE => () | |
148 | | SOME n' => | |
149 | let | |
150 | val _ = Node.clearNext n | |
151 | fun loop (n, n' as Node.T {next, ...}) = | |
152 | let | |
153 | val no = !next | |
154 | val _ = next := SOME n | |
155 | in | |
156 | case no of | |
157 | NONE => () | |
158 | | SOME n'' => loop (n', n'') | |
159 | end | |
160 | val _ = loop (n, n') | |
161 | val _ = Ref.swap (first, last) | |
162 | in | |
163 | () | |
164 | end | |
165 | ; if invariant ll | |
166 | then () | |
167 | else Out.output (Out.error, "reverse 2\n")) | |
168 | ||
169 | fun fromList l = | |
170 | unfold (l, | |
171 | fn [] => NONE | |
172 | | x :: l => SOME (x, l)) | |
173 | ||
174 | end |