|
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