forked from functionaljava/functionaljava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathF2.java
More file actions
368 lines (341 loc) · 12 KB
/
F2.java
File metadata and controls
368 lines (341 loc) · 12 KB
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
package fj;
import fj.control.parallel.Promise;
import fj.data.Array;
import fj.data.IterableW;
import fj.data.List;
import fj.data.NonEmptyList;
import fj.data.Option;
import fj.data.Set;
import fj.data.Stream;
import fj.data.Tree;
import fj.data.TreeZipper;
import fj.data.Zipper;
import static fj.data.Tree.node;
import static fj.P.p;
import static fj.data.IterableW.wrap;
import static fj.data.Set.iterableSet;
import static fj.data.TreeZipper.treeZipper;
import static fj.data.Zipper.zipper;
/**
* A transformation function of arity-2 from <code>A</code> and <code>B</code> to <code>C</code>.
* This type can be represented using the Java 7 closure syntax.
*
* @version %build.number%
*/
public abstract class F2<A, B, C> {
/**
* Transform <code>A</code> and <code>B</code> to <code>C</code>.
*
* @param a The <code>A</code> to transform.
* @param b The <code>B</code> to transform.
* @return The result of the transformation.
*/
public abstract C f(A a, B b);
/**
* Partial application.
*
* @param a The <code>A</code> to which to apply this function.
* @return The function partially applied to the given argument.
*/
public final F<B, C> f(final A a) {
return new F<B, C>() {
public C f(final B b) {
return F2.this.f(a, b);
}
};
}
/**
* Curries this wrapped function to a wrapped function of arity-1 that returns another wrapped function.
*
* @return a wrapped function of arity-1 that returns another wrapped function.
*/
public final F<A, F<B, C>> curry() {
return new F<A, F<B, C>>() {
public F<B, C> f(final A a) {
return new F<B, C>() {
public C f(final B b) {
return F2.this.f(a, b);
}
};
}
};
}
/**
* Flips the arguments of this function.
*
* @return A new function with the arguments of this function flipped.
*/
public final F2<B, A, C> flip() {
return new F2<B, A, C>() {
public C f(final B b, final A a) {
return F2.this.f(a, b);
}
};
}
/**
* Uncurries this function to a function on tuples.
*
* @return A new function that calls this function with the elements of a given tuple.
*/
public final F<P2<A, B>, C> tuple() {
return new F<P2<A, B>, C>() {
public C f(final P2<A, B> p) {
return F2.this.f(p._1(), p._2());
}
};
}
/**
* Promotes this function to a function on Arrays.
*
* @return This function promoted to transform Arrays.
*/
public final F2<Array<A>, Array<B>, Array<C>> arrayM() {
return new F2<Array<A>, Array<B>, Array<C>>() {
public Array<C> f(final Array<A> a, final Array<B> b) {
return a.bind(b, F2.this.curry());
}
};
}
/**
* Promotes this function to a function on Promises.
*
* @return This function promoted to transform Promises.
*/
public final F2<Promise<A>, Promise<B>, Promise<C>> promiseM() {
return new F2<Promise<A>, Promise<B>, Promise<C>>() {
public Promise<C> f(final Promise<A> a, final Promise<B> b) {
return a.bind(b, F2.this.curry());
}
};
}
/**
* Promotes this function to a function on Iterables.
*
* @return This function promoted to transform Iterables.
*/
public final F2<Iterable<A>, Iterable<B>, IterableW<C>> iterableM() {
return new F2<Iterable<A>, Iterable<B>, IterableW<C>>() {
public IterableW<C> f(final Iterable<A> a, final Iterable<B> b) {
return IterableW.liftM2(F2.this.curry()).f(a).f(b);
}
};
}
/**
* Promotes this function to a function on Lists.
*
* @return This function promoted to transform Lists.
*/
public final F2<List<A>, List<B>, List<C>> listM() {
return new F2<List<A>, List<B>, List<C>>() {
public List<C> f(final List<A> a, final List<B> b) {
return List.liftM2(F2.this.curry()).f(a).f(b);
}
};
}
/**
* Promotes this function to a function on non-empty lists.
*
* @return This function promoted to transform non-empty lists.
*/
public final F2<NonEmptyList<A>, NonEmptyList<B>, NonEmptyList<C>> nelM() {
return new F2<NonEmptyList<A>, NonEmptyList<B>, NonEmptyList<C>>() {
public NonEmptyList<C> f(final NonEmptyList<A> as, final NonEmptyList<B> bs) {
return NonEmptyList.fromList(as.toList().bind(bs.toList(), F2.this)).some();
}
};
}
/**
* Promotes this function to a function on Options.
*
* @return This function promoted to transform Options.
*/
public final F2<Option<A>, Option<B>, Option<C>> optionM() {
return new F2<Option<A>, Option<B>, Option<C>>() {
public Option<C> f(final Option<A> a, final Option<B> b) {
return Option.liftM2(F2.this.curry()).f(a).f(b);
}
};
}
/**
* Promotes this function to a function on Sets.
*
* @param o An ordering for the result of the promoted function.
* @return This function promoted to transform Sets.
*/
public final F2<Set<A>, Set<B>, Set<C>> setM(final Ord<C> o) {
return new F2<Set<A>, Set<B>, Set<C>>() {
public Set<C> f(final Set<A> as, final Set<B> bs) {
Set<C> cs = Set.empty(o);
for (final A a : as)
for (final B b : bs)
cs = cs.insert(F2.this.f(a, b));
return cs;
}
};
}
/**
* Promotes this function to a function on Streams.
*
* @return This function promoted to transform Streams.
*/
public final F2<Stream<A>, Stream<B>, Stream<C>> streamM() {
return new F2<Stream<A>, Stream<B>, Stream<C>>() {
public Stream<C> f(final Stream<A> as, final Stream<B> bs) {
return as.bind(bs, F2.this);
}
};
}
/**
* Promotes this function to a function on Trees.
*
* @return This function promoted to transform Trees.
*/
public final F2<Tree<A>, Tree<B>, Tree<C>> treeM() {
return new F2<Tree<A>, Tree<B>, Tree<C>>() {
public Tree<C> f(final Tree<A> as, final Tree<B> bs) {
final F2<Tree<A>, Tree<B>, Tree<C>> self = this;
return node(F2.this.f(as.root(), bs.root()), new P1<Stream<Tree<C>>>() {
public Stream<Tree<C>> _1() {
return self.streamM().f(as.subForest()._1(), bs.subForest()._1());
}
});
}
};
}
/**
* Promotes this function to zip two arrays, applying the function lock-step over both Arrays.
*
* @return A function that zips two arrays with this function.
*/
public final F2<Array<A>, Array<B>, Array<C>> zipArrayM() {
return new F2<Array<A>, Array<B>, Array<C>>() {
public Array<C> f(final Array<A> as, final Array<B> bs) {
return as.zipWith(bs, F2.this);
}
};
}
/**
* Promotes this function to zip two iterables, applying the function lock-step over both iterables.
*
* @return A function that zips two iterables with this function.
*/
public final F2<Iterable<A>, Iterable<B>, Iterable<C>> zipIterableM() {
return new F2<Iterable<A>, Iterable<B>, Iterable<C>>() {
public Iterable<C> f(final Iterable<A> as, final Iterable<B> bs) {
return wrap(as).zipWith(bs, F2.this);
}
};
}
/**
* Promotes this function to zip two lists, applying the function lock-step over both lists.
*
* @return A function that zips two lists with this function.
*/
public final F2<List<A>, List<B>, List<C>> zipListM() {
return new F2<List<A>, List<B>, List<C>>() {
public List<C> f(final List<A> as, final List<B> bs) {
return as.zipWith(bs, F2.this);
}
};
}
/**
* Promotes this function to zip two streams, applying the function lock-step over both streams.
*
* @return A function that zips two streams with this function.
*/
public final F2<Stream<A>, Stream<B>, Stream<C>> zipStreamM() {
return new F2<Stream<A>, Stream<B>, Stream<C>>() {
public Stream<C> f(final Stream<A> as, final Stream<B> bs) {
return as.zipWith(bs, F2.this);
}
};
}
/**
* Promotes this function to zip two non-empty lists, applying the function lock-step over both lists.
*
* @return A function that zips two non-empty lists with this function.
*/
public final F2<NonEmptyList<A>, NonEmptyList<B>, NonEmptyList<C>> zipNelM() {
return new F2<NonEmptyList<A>, NonEmptyList<B>, NonEmptyList<C>>() {
public NonEmptyList<C> f(final NonEmptyList<A> as, final NonEmptyList<B> bs) {
return NonEmptyList.fromList(as.toList().zipWith(bs.toList(), F2.this)).some();
}
};
}
/**
* Promotes this function to zip two sets, applying the function lock-step over both sets.
*
* @param o An ordering for the resulting set.
* @return A function that zips two sets with this function.
*/
public final F2<Set<A>, Set<B>, Set<C>> zipSetM(final Ord<C> o) {
return new F2<Set<A>, Set<B>, Set<C>>() {
public Set<C> f(final Set<A> as, final Set<B> bs) {
return iterableSet(o, as.toStream().zipWith(bs.toStream(), F2.this));
}
};
}
/**
* Promotes this function to zip two trees, applying the function lock-step over both trees.
* The structure of the resulting tree is the structural intersection of the two trees.
*
* @return A function that zips two trees with this function.
*/
public final F2<Tree<A>, Tree<B>, Tree<C>> zipTreeM() {
return new F2<Tree<A>, Tree<B>, Tree<C>>() {
public Tree<C> f(final Tree<A> ta, final Tree<B> tb) {
final F2<Tree<A>, Tree<B>, Tree<C>> self = this;
return node(F2.this.f(ta.root(), tb.root()), new P1<Stream<Tree<C>>>() {
public Stream<Tree<C>> _1() {
return self.zipStreamM().f(ta.subForest()._1(), tb.subForest()._1());
}
});
}
};
}
/**
* Promotes this function to zip two zippers, applying the function lock-step over both zippers in both directions.
* The structure of the resulting zipper is the structural intersection of the two zippers.
*
* @return A function that zips two zippers with this function.
*/
public final F2<Zipper<A>, Zipper<B>, Zipper<C>> zipZipperM() {
return new F2<Zipper<A>, Zipper<B>, Zipper<C>>() {
@SuppressWarnings({"unchecked"})
public Zipper<C> f(final Zipper<A> ta, final Zipper<B> tb) {
final F2<Stream<A>, Stream<B>, Stream<C>> sf = F2.this.zipStreamM();
return zipper(sf.f(ta.lefts(), tb.lefts()), F2.this.f(ta.focus(), tb.focus()), sf.f(ta.rights(), tb.rights()));
}
};
}
/**
* Promotes this function to zip two TreeZippers, applying the function lock-step over both zippers in all directions.
* The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers.
*
* @return A function that zips two TreeZippers with this function.
*/
public final F2<TreeZipper<A>, TreeZipper<B>, TreeZipper<C>> zipTreeZipperM() {
return new F2<TreeZipper<A>, TreeZipper<B>, TreeZipper<C>>() {
@SuppressWarnings({"unchecked"})
public TreeZipper<C> f(final TreeZipper<A> ta, final TreeZipper<B> tb) {
final F2<Stream<Tree<A>>, Stream<Tree<B>>, Stream<Tree<C>>> sf = F2.this.treeM().zipStreamM();
final
F2<Stream<P3<Stream<Tree<A>>, A, Stream<Tree<A>>>>,
Stream<P3<Stream<Tree<B>>, B, Stream<Tree<B>>>>,
Stream<P3<Stream<Tree<C>>, C, Stream<Tree<C>>>>>
pf =
new F2<P3<Stream<Tree<A>>, A, Stream<Tree<A>>>,
P3<Stream<Tree<B>>, B, Stream<Tree<B>>>,
P3<Stream<Tree<C>>, C, Stream<Tree<C>>>>() {
public P3<Stream<Tree<C>>, C, Stream<Tree<C>>> f(final P3<Stream<Tree<A>>, A, Stream<Tree<A>>> pa,
final P3<Stream<Tree<B>>, B, Stream<Tree<B>>> pb) {
return p(F2.this.treeM().zipStreamM().f(pa._1(), pb._1()), F2.this.f(pa._2(), pb._2()),
F2.this.treeM().zipStreamM().f(pa._3(), pb._3()));
}
}.zipStreamM();
return treeZipper(F2.this.treeM().f(ta.p()._1(), tb.p()._1()), sf.f(ta.lefts(), tb.lefts()),
sf.f(ta.rights(), tb.rights()), pf.f(ta.p()._4(), tb.p()._4()));
}
};
}
}