|
1 | 1 | package fj.data;
|
2 | 2 |
|
3 |
| -import static fj.Bottom.errorF; |
4 |
| -import static fj.Function.constant; |
5 |
| -import static fj.Function.partialApply2; |
| 3 | +import fj.F; |
| 4 | +import fj.F0; |
| 5 | +import fj.F1Functions; |
| 6 | +import fj.F2; |
| 7 | +import fj.Function; |
| 8 | +import fj.P; |
| 9 | +import fj.P1; |
| 10 | +import fj.P2; |
| 11 | +import fj.Try; |
| 12 | +import fj.Unit; |
| 13 | +import fj.data.Iteratee.Input; |
| 14 | +import fj.data.Iteratee.IterV; |
| 15 | +import fj.function.Try0; |
| 16 | +import fj.function.Try1; |
6 | 17 |
|
7 | 18 | import java.io.BufferedReader;
|
8 | 19 | import java.io.Closeable;
|
|
14 | 25 | import java.nio.charset.Charset;
|
15 | 26 | import java.util.Arrays;
|
16 | 27 |
|
17 |
| -import fj.*; |
18 |
| -import fj.data.Iteratee.Input; |
19 |
| -import fj.data.Iteratee.IterV; |
20 |
| -import fj.function.Try0; |
21 |
| -import fj.function.Try1; |
| 28 | +import static fj.Bottom.errorF; |
| 29 | +import static fj.Function.constant; |
| 30 | +import static fj.Function.partialApply2; |
22 | 31 |
|
23 | 32 | /**
|
24 | 33 | * IO monad for processing files, with main methods {@link #enumFileLines },
|
@@ -170,130 +179,129 @@ public static <A> SafeIO<A> lazySafe(final F0<A> f) {
|
170 | 179 | * A function that feeds an iteratee with lines read from a {@link BufferedReader}.
|
171 | 180 | */
|
172 | 181 | public static <A> F<BufferedReader, F<IterV<String, A>, IO<IterV<String, A>>>> lineReader() {
|
173 |
| - final F<IterV<String, A>, Boolean> isDone = |
174 |
| - new F<Iteratee.IterV<String, A>, Boolean>() { |
175 |
| - final F<P2<A, Input<String>>, P1<Boolean>> done = constant(P.p(true)); |
176 |
| - final F<F<Input<String>, IterV<String, A>>, P1<Boolean>> cont = constant(P.p(false)); |
177 |
| - |
178 |
| - @Override |
179 |
| - public Boolean f(final IterV<String, A> i) { |
180 |
| - return i.fold(done, cont)._1(); |
181 |
| - } |
182 |
| - }; |
183 |
| - |
184 |
| - return r -> new F<IterV<String, A>, IO<IterV<String, A>>>() { |
185 |
| - final F<P2<A, Input<String>>, P1<IterV<String, A>>> done = errorF("iteratee is done"); //$NON-NLS-1$ |
186 |
| - |
187 |
| - @Override |
188 |
| - public IO<IterV<String, A>> f(final IterV<String, A> it) { |
189 |
| - // use loop instead of recursion because of missing TCO |
190 |
| - return () -> { |
191 |
| - IterV<String, A> i = it; |
192 |
| - while (!isDone.f(i)) { |
193 |
| - final String s = r.readLine(); |
194 |
| - if (s == null) { |
195 |
| - return i; |
196 |
| - } |
197 |
| - final Input<String> input = Input.el(s); |
198 |
| - final F<F<Input<String>, IterV<String, A>>, P1<IterV<String, A>>> cont = F1Functions.lazy(Function.apply(input)); |
199 |
| - i = i.fold(done, cont)._1(); |
| 182 | + return LineReader::new; |
| 183 | + } |
| 184 | + |
| 185 | + private static class LineReader<A> implements F<IterV<String, A>, IO<IterV<String, A>>> { |
| 186 | + |
| 187 | + private final BufferedReader r; |
| 188 | + |
| 189 | + private final F<IterV<String, A>, Boolean> isDone = i -> i.fold(constant(P.p(true)), constant(P.p(false)))._1(); |
| 190 | + private final F<P2<A, Input<String>>, P1<IterV<String, A>>> done = errorF("iteratee is done"); //$NON-NLS-1$ |
| 191 | + |
| 192 | + private LineReader(BufferedReader r) { |
| 193 | + this.r = r; |
| 194 | + } |
| 195 | + |
| 196 | + @Override |
| 197 | + public IO<IterV<String, A>> f(IterV<String, A> it) { |
| 198 | + // use loop instead of recursion because of missing TCO |
| 199 | + return () -> { |
| 200 | + IterV<String, A> i = it; |
| 201 | + while (!isDone.f(i)) { |
| 202 | + final String s = r.readLine(); |
| 203 | + if (s == null) { |
| 204 | + return i; |
200 | 205 | }
|
201 |
| - return i; |
202 |
| - }; |
203 |
| - } |
204 |
| - }; |
| 206 | + final Input<String> input = Input.el(s); |
| 207 | + final F<F<Input<String>, IterV<String, A>>, P1<IterV<String, A>>> cont = F1Functions.lazy(Function.apply(input)); |
| 208 | + i = i.fold(done, cont)._1(); |
| 209 | + } |
| 210 | + return i; |
| 211 | + }; |
| 212 | + } |
205 | 213 | }
|
206 | 214 |
|
207 | 215 | /**
|
208 | 216 | * A function that feeds an iteratee with character chunks read from a {@link Reader}
|
209 | 217 | * (char[] of size {@link #DEFAULT_BUFFER_SIZE}).
|
210 | 218 | */
|
211 | 219 | public static <A> F<Reader, F<IterV<char[], A>, IO<IterV<char[], A>>>> charChunkReader() {
|
212 |
| - final F<IterV<char[], A>, Boolean> isDone = |
213 |
| - new F<Iteratee.IterV<char[], A>, Boolean>() { |
214 |
| - final F<P2<A, Input<char[]>>, P1<Boolean>> done = constant(P.p(true)); |
215 |
| - final F<F<Input<char[]>, IterV<char[], A>>, P1<Boolean>> cont = constant(P.p(false)); |
216 |
| - |
217 |
| - @Override |
218 |
| - public Boolean f(final IterV<char[], A> i) { |
219 |
| - return i.fold(done, cont)._1(); |
| 220 | + return CharChunkReader::new; |
| 221 | + } |
| 222 | + |
| 223 | + private static class CharChunkReader<A> implements F<IterV<char[], A>, IO<IterV<char[], A>>> { |
| 224 | + |
| 225 | + private final Reader r; |
| 226 | + |
| 227 | + private final F<IterV<char[], A>, Boolean> isDone = i -> i.fold(constant(P.p(true)), constant(P.p(false)))._1(); |
| 228 | + private final F<P2<A, Input<char[]>>, P1<IterV<char[], A>>> done = errorF("iteratee is done"); //$NON-NLS-1$ |
| 229 | + |
| 230 | + CharChunkReader(Reader r) { |
| 231 | + this.r = r; |
| 232 | + } |
| 233 | + |
| 234 | + @Override |
| 235 | + public IO<IterV<char[], A>> f(IterV<char[], A> it) { |
| 236 | + // use loop instead of recursion because of missing TCO |
| 237 | + return () -> { |
| 238 | + |
| 239 | + IterV<char[], A> i = it; |
| 240 | + while (!isDone.f(i)) { |
| 241 | + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; |
| 242 | + final int numRead = r.read(buffer); |
| 243 | + if (numRead == -1) { |
| 244 | + return i; |
220 | 245 | }
|
221 |
| - }; |
222 |
| - |
223 |
| - return r -> new F<IterV<char[], A>, IO<IterV<char[], A>>>() { |
224 |
| - final F<P2<A, Input<char[]>>, P1<IterV<char[], A>>> done = errorF("iteratee is done"); //$NON-NLS-1$ |
225 |
| - |
226 |
| - @Override |
227 |
| - public IO<IterV<char[], A>> f(final IterV<char[], A> it) { |
228 |
| - // use loop instead of recursion because of missing TCO |
229 |
| - return () -> { |
230 |
| - |
231 |
| - IterV<char[], A> i = it; |
232 |
| - while (!isDone.f(i)) { |
233 |
| - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; |
234 |
| - final int numRead = r.read(buffer); |
235 |
| - if (numRead == -1) { |
236 |
| - return i; |
237 |
| - } |
238 |
| - if (numRead < buffer.length) { |
239 |
| - buffer = Arrays.copyOfRange(buffer, 0, numRead); |
240 |
| - } |
241 |
| - final Input<char[]> input = Input.el(buffer); |
242 |
| - final F<F<Input<char[]>, IterV<char[], A>>, P1<IterV<char[], A>>> cont = |
243 |
| - F1Functions.lazy(Function.apply(input)); |
244 |
| - i = i.fold(done, cont)._1(); |
| 246 | + if (numRead < buffer.length) { |
| 247 | + buffer = Arrays.copyOfRange(buffer, 0, numRead); |
245 | 248 | }
|
246 |
| - return i; |
247 |
| - }; |
248 |
| - } |
249 |
| - }; |
| 249 | + final Input<char[]> input = Input.el(buffer); |
| 250 | + final F<F<Input<char[]>, IterV<char[], A>>, P1<IterV<char[], A>>> cont = |
| 251 | + F1Functions.lazy(Function.apply(input)); |
| 252 | + i = i.fold(done, cont)._1(); |
| 253 | + } |
| 254 | + return i; |
| 255 | + }; |
| 256 | + } |
250 | 257 | }
|
251 | 258 |
|
| 259 | + |
| 260 | + |
252 | 261 | /**
|
253 | 262 | * A function that feeds an iteratee with characters read from a {@link Reader}
|
254 | 263 | * (chars are read in chunks of size {@link #DEFAULT_BUFFER_SIZE}).
|
255 | 264 | */
|
256 | 265 | public static <A> F<Reader, F<IterV<Character, A>, IO<IterV<Character, A>>>> charChunkReader2() {
|
257 |
| - final F<IterV<Character, A>, Boolean> isDone = |
258 |
| - new F<Iteratee.IterV<Character, A>, Boolean>() { |
259 |
| - final F<P2<A, Input<Character>>, P1<Boolean>> done = constant(P.p(true)); |
260 |
| - final F<F<Input<Character>, IterV<Character, A>>, P1<Boolean>> cont = constant(P.p(false)); |
261 |
| - |
262 |
| - @Override |
263 |
| - public Boolean f(final IterV<Character, A> i) { |
264 |
| - return i.fold(done, cont)._1(); |
| 266 | + return CharChunkReader2::new; |
| 267 | + } |
| 268 | + |
| 269 | + private static class CharChunkReader2<A> implements F<IterV<Character, A>, IO<IterV<Character, A>>> { |
| 270 | + |
| 271 | + private final Reader r; |
| 272 | + |
| 273 | + private final F<IterV<Character, A>, Boolean> isDone = i -> i.fold(constant(P.p(true)), constant(P.p(false)))._1(); |
| 274 | + private final F<P2<A, Input<Character>>, IterV<Character, A>> done = errorF("iteratee is done"); //$NON-NLS-1$ |
| 275 | + |
| 276 | + CharChunkReader2(Reader r) { |
| 277 | + this.r = r; |
| 278 | + } |
| 279 | + |
| 280 | + @Override |
| 281 | + public IO<IterV<Character, A>> f(IterV<Character, A> it) { |
| 282 | + // use loop instead of recursion because of missing TCO |
| 283 | + return () -> { |
| 284 | + |
| 285 | + IterV<Character, A> i = it; |
| 286 | + while (!isDone.f(i)) { |
| 287 | + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; |
| 288 | + final int numRead = r.read(buffer); |
| 289 | + if (numRead == -1) { |
| 290 | + return i; |
265 | 291 | }
|
266 |
| - }; |
267 |
| - |
268 |
| - return r -> new F<IterV<Character, A>, IO<IterV<Character, A>>>() { |
269 |
| - final F<P2<A, Input<Character>>, IterV<Character, A>> done = errorF("iteratee is done"); //$NON-NLS-1$ |
270 |
| - |
271 |
| - @Override |
272 |
| - public IO<IterV<Character, A>> f(final IterV<Character, A> it) { |
273 |
| - // use loop instead of recursion because of missing TCO |
274 |
| - return () -> { |
275 |
| - |
276 |
| - IterV<Character, A> i = it; |
277 |
| - while (!isDone.f(i)) { |
278 |
| - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; |
279 |
| - final int numRead = r.read(buffer); |
280 |
| - if (numRead == -1) { |
281 |
| - return i; |
282 |
| - } |
283 |
| - if (numRead < buffer.length) { |
284 |
| - buffer = Arrays.copyOfRange(buffer, 0, numRead); |
285 |
| - } |
286 |
| - for (char c : buffer) { |
287 |
| - final Input<Character> input = Input.el(c); |
288 |
| - final F<F<Input<Character>, IterV<Character, A>>, IterV<Character, A>> cont = |
289 |
| - Function.apply(input); |
290 |
| - i = i.fold(done, cont); |
291 |
| - } |
| 292 | + if (numRead < buffer.length) { |
| 293 | + buffer = Arrays.copyOfRange(buffer, 0, numRead); |
292 | 294 | }
|
293 |
| - return i; |
294 |
| - }; |
295 |
| - } |
296 |
| - }; |
| 295 | + for (char c : buffer) { |
| 296 | + final Input<Character> input = Input.el(c); |
| 297 | + final F<F<Input<Character>, IterV<Character, A>>, IterV<Character, A>> cont = |
| 298 | + Function.apply(input); |
| 299 | + i = i.fold(done, cont); |
| 300 | + } |
| 301 | + } |
| 302 | + return i; |
| 303 | + }; |
| 304 | + } |
297 | 305 | }
|
298 | 306 |
|
299 | 307 | public static <A, B> IO<B> map(final IO<A> io, final F<A, B> f) {
|
|
0 commit comments