comparison src/main/java/fj/F2Functions.java @ 0:fe80c1edf1be

add getLoop
author tatsuki
date Fri, 20 Mar 2015 21:04:03 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:fe80c1edf1be
1 package fj;
2
3 import fj.control.parallel.Promise;
4 import fj.data.*;
5 import fj.function.Try2;
6
7 import static fj.P.p;
8 import static fj.data.IterableW.wrap;
9 import static fj.data.Set.iterableSet;
10 import static fj.data.Tree.node;
11 import static fj.data.TreeZipper.treeZipper;
12 import static fj.data.Zipper.zipper;
13
14 /**
15 * Created by MarkPerry on 6/04/2014.
16 */
17 public class F2Functions {
18
19
20 /**
21 * Partial application.
22 *
23 * @param a The <code>A</code> to which to apply this function.
24 * @return The function partially applied to the given argument.
25 */
26 static public <A, B, C> F<B, C> f(final F2<A, B, C> f, final A a) {
27 return new F<B, C>() {
28 public C f(final B b) {
29 return f.f(a, b);
30 }
31 };
32 }
33
34 /**
35 * Curries this wrapped function to a wrapped function of arity-1 that returns another wrapped function.
36 *
37 * @return a wrapped function of arity-1 that returns another wrapped function.
38 */
39 static public <A, B, C> F<A, F<B, C>> curry(final F2<A, B, C> f) {
40 return new F<A, F<B, C>>() {
41 public F<B, C> f(final A a) {
42 return new F<B, C>() {
43 public C f(final B b) {
44 return f.f(a, b);
45 }
46 };
47 }
48 };
49 }
50
51 /**
52 * Flips the arguments of this function.
53 *
54 * @return A new function with the arguments of this function flipped.
55 */
56 static public <A, B, C> F2<B, A, C> flip(final F2<A, B, C> f) {
57 return new F2<B, A, C>() {
58 public C f(final B b, final A a) {
59 return f.f(a, b);
60 }
61 };
62 }
63
64 /**
65 * Uncurries this function to a function on tuples.
66 *
67 * @return A new function that calls this function with the elements of a given tuple.
68 */
69 static public <A, B, C> F<P2<A, B>, C> tuple(final F2<A, B, C> f) {
70 return new F<P2<A, B>, C>() {
71 public C f(final P2<A, B> p) {
72 return f.f(p._1(), p._2());
73 }
74 };
75 }
76
77 /**
78 * Promotes this function to a function on Arrays.
79 *
80 * @return This function promoted to transform Arrays.
81 */
82 static public <A, B, C> F2<Array<A>, Array<B>, Array<C>> arrayM(final F2<A, B, C> f) {
83 return new F2<Array<A>, Array<B>, Array<C>>() {
84 public Array<C> f(final Array<A> a, final Array<B> b) {
85 return a.bind(b, curry(f));
86 }
87 };
88 }
89
90 /**
91 * Promotes this function to a function on Promises.
92 *
93 * @return This function promoted to transform Promises.
94 */
95 static public <A, B, C> F2<Promise<A>, Promise<B>, Promise<C>> promiseM(final F2<A, B, C> f) {
96 return new F2<Promise<A>, Promise<B>, Promise<C>>() {
97 public Promise<C> f(final Promise<A> a, final Promise<B> b) {
98 return a.bind(b, curry(f));
99 }
100 };
101 }
102
103 /**
104 * Promotes this function to a function on Iterables.
105 *
106 * @return This function promoted to transform Iterables.
107 */
108 static public <A, B, C> F2<Iterable<A>, Iterable<B>, IterableW<C>> iterableM(final F2<A, B, C> f) {
109 return new F2<Iterable<A>, Iterable<B>, IterableW<C>>() {
110 public IterableW<C> f(final Iterable<A> a, final Iterable<B> b) {
111 return IterableW.liftM2(curry(f)).f(a).f(b);
112 }
113 };
114 }
115
116 /**
117 * Promotes this function to a function on Lists.
118 *
119 * @return This function promoted to transform Lists.
120 */
121 static public <A, B, C> F2<List<A>, List<B>, List<C>> listM(final F2<A, B, C> f) {
122 return new F2<List<A>, List<B>, List<C>>() {
123 public List<C> f(final List<A> a, final List<B> b) {
124 return List.liftM2(curry(f)).f(a).f(b);
125 }
126 };
127 }
128
129 /**
130 * Promotes this function to a function on non-empty lists.
131 *
132 * @return This function promoted to transform non-empty lists.
133 */
134 static public <A, B, C> F2<NonEmptyList<A>, NonEmptyList<B>, NonEmptyList<C>> nelM(final F2<A, B, C> f) {
135 return new F2<NonEmptyList<A>, NonEmptyList<B>, NonEmptyList<C>>() {
136 public NonEmptyList<C> f(final NonEmptyList<A> as, final NonEmptyList<B> bs) {
137 return NonEmptyList.fromList(as.toList().bind(bs.toList(), f)).some();
138 }
139 };
140 }
141
142 /**
143 * Promotes this function to a function on Options.
144 *
145 * @return This function promoted to transform Options.
146 */
147 static public <A, B, C> F2<Option<A>, Option<B>, Option<C>> optionM(final F2<A, B, C> f) {
148 return new F2<Option<A>, Option<B>, Option<C>>() {
149 public Option<C> f(final Option<A> a, final Option<B> b) {
150 return Option.liftM2(curry(f)).f(a).f(b);
151 }
152 };
153 }
154
155 /**
156 * Promotes this function to a function on Sets.
157 *
158 * @param o An ordering for the result of the promoted function.
159 * @return This function promoted to transform Sets.
160 */
161 static public <A, B, C> F2<Set<A>, Set<B>, Set<C>> setM(final F2<A, B, C> f, final Ord<C> o) {
162 return new F2<Set<A>, Set<B>, Set<C>>() {
163 public Set<C> f(final Set<A> as, final Set<B> bs) {
164 Set<C> cs = Set.empty(o);
165 for (final A a : as)
166 for (final B b : bs)
167 cs = cs.insert(f.f(a, b));
168 return cs;
169 }
170 };
171 }
172
173 /**
174 * Promotes this function to a function on Streams.
175 *
176 * @return This function promoted to transform Streams.
177 */
178 static public <A, B, C> F2<Stream<A>, Stream<B>, Stream<C>> streamM(final F2<A, B, C> f) {
179 return new F2<Stream<A>, Stream<B>, Stream<C>>() {
180 public Stream<C> f(final Stream<A> as, final Stream<B> bs) {
181 return as.bind(bs, f);
182 }
183 };
184 }
185
186 /**
187 * Promotes this function to a function on Trees.
188 *
189 * @return This function promoted to transform Trees.
190 */
191 static public <A, B, C> F2<Tree<A>, Tree<B>, Tree<C>> treeM(final F2<A, B, C> f) {
192 return new F2<Tree<A>, Tree<B>, Tree<C>>() {
193 public Tree<C> f(final Tree<A> as, final Tree<B> bs) {
194 final F2<Tree<A>, Tree<B>, Tree<C>> self = this;
195 return node(f.f(as.root(), bs.root()), new P1<Stream<Tree<C>>>() {
196 public Stream<Tree<C>> _1() {
197 return streamM(self).f(as.subForest()._1(), bs.subForest()._1());
198 }
199 });
200 }
201 };
202 }
203
204 /**
205 * Promotes this function to zip two arrays, applying the function lock-step over both Arrays.
206 *
207 * @return A function that zips two arrays with this function.
208 */
209 static public <A, B, C> F2<Array<A>, Array<B>, Array<C>> zipArrayM(final F2<A, B, C> f) {
210 return new F2<Array<A>, Array<B>, Array<C>>() {
211 public Array<C> f(final Array<A> as, final Array<B> bs) {
212 return as.zipWith(bs, f);
213 }
214 };
215 }
216
217 /**
218 * Promotes this function to zip two iterables, applying the function lock-step over both iterables.
219 *
220 * @return A function that zips two iterables with this function.
221 */
222 static public <A, B, C> F2<Iterable<A>, Iterable<B>, Iterable<C>> zipIterableM(final F2<A, B, C> f) {
223 return new F2<Iterable<A>, Iterable<B>, Iterable<C>>() {
224 public Iterable<C> f(final Iterable<A> as, final Iterable<B> bs) {
225 return wrap(as).zipWith(bs, f);
226 }
227 };
228 }
229
230 /**
231 * Promotes this function to zip two lists, applying the function lock-step over both lists.
232 *
233 * @return A function that zips two lists with this function.
234 */
235 static public <A, B, C> F2<List<A>, List<B>, List<C>> zipListM(final F2<A, B, C> f) {
236 return new F2<List<A>, List<B>, List<C>>() {
237 public List<C> f(final List<A> as, final List<B> bs) {
238 return as.zipWith(bs, f);
239 }
240 };
241 }
242
243
244 /**
245 * Promotes this function to zip two streams, applying the function lock-step over both streams.
246 *
247 * @return A function that zips two streams with this function.
248 */
249 static public <A, B, C> F2<Stream<A>, Stream<B>, Stream<C>> zipStreamM(final F2<A, B, C> f) {
250 return new F2<Stream<A>, Stream<B>, Stream<C>>() {
251 public Stream<C> f(final Stream<A> as, final Stream<B> bs) {
252 return as.zipWith(bs, f);
253 }
254 };
255 }
256
257 /**
258 * Promotes this function to zip two non-empty lists, applying the function lock-step over both lists.
259 *
260 * @return A function that zips two non-empty lists with this function.
261 */
262 static public <A, B, C> F2<NonEmptyList<A>, NonEmptyList<B>, NonEmptyList<C>> zipNelM(final F2<A, B, C> f) {
263 return new F2<NonEmptyList<A>, NonEmptyList<B>, NonEmptyList<C>>() {
264 public NonEmptyList<C> f(final NonEmptyList<A> as, final NonEmptyList<B> bs) {
265 return NonEmptyList.fromList(as.toList().zipWith(bs.toList(), f)).some();
266 }
267 };
268 }
269
270 /**
271 * Promotes this function to zip two sets, applying the function lock-step over both sets.
272 *
273 * @param o An ordering for the resulting set.
274 * @return A function that zips two sets with this function.
275 */
276 static public <A, B, C> F2<Set<A>, Set<B>, Set<C>> zipSetM(final F2<A, B, C> f, final Ord<C> o) {
277 return new F2<Set<A>, Set<B>, Set<C>>() {
278 public Set<C> f(final Set<A> as, final Set<B> bs) {
279 return iterableSet(o, as.toStream().zipWith(bs.toStream(), f));
280 }
281 };
282 }
283
284 /**
285 * Promotes this function to zip two trees, applying the function lock-step over both trees.
286 * The structure of the resulting tree is the structural intersection of the two trees.
287 *
288 * @return A function that zips two trees with this function.
289 */
290 static public <A, B, C> F2<Tree<A>, Tree<B>, Tree<C>> zipTreeM(final F2<A, B, C> f) {
291 return new F2<Tree<A>, Tree<B>, Tree<C>>() {
292 public Tree<C> f(final Tree<A> ta, final Tree<B> tb) {
293 final F2<Tree<A>, Tree<B>, Tree<C>> self = this;
294 return node(f.f(ta.root(), tb.root()), new P1<Stream<Tree<C>>>() {
295 public Stream<Tree<C>> _1() {
296 return zipStreamM(self).f(ta.subForest()._1(), tb.subForest()._1());
297 }
298 });
299 }
300 };
301 }
302
303 /**
304 * Promotes this function to zip two zippers, applying the function lock-step over both zippers in both directions.
305 * The structure of the resulting zipper is the structural intersection of the two zippers.
306 *
307 * @return A function that zips two zippers with this function.
308 */
309 static public <A, B, C> F2<Zipper<A>, Zipper<B>, Zipper<C>> zipZipperM(final F2<A, B, C> f) {
310 return new F2<Zipper<A>, Zipper<B>, Zipper<C>>() {
311 @SuppressWarnings({"unchecked"})
312 public Zipper<C> f(final Zipper<A> ta, final Zipper<B> tb) {
313 final F2<Stream<A>, Stream<B>, Stream<C>> sf = zipStreamM(f);
314 return zipper(sf.f(ta.lefts(), tb.lefts()), f.f(ta.focus(), tb.focus()), sf.f(ta.rights(), tb.rights()));
315 }
316 };
317 }
318
319 /**
320 * Promotes this function to zip two TreeZippers, applying the function lock-step over both zippers in all directions.
321 * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers.
322 *
323 * @return A function that zips two TreeZippers with this function.
324 */
325 static public <A, B, C> F2<TreeZipper<A>, TreeZipper<B>, TreeZipper<C>> zipTreeZipperM(final F2<A, B, C> f) {
326 return new F2<TreeZipper<A>, TreeZipper<B>, TreeZipper<C>>() {
327 @SuppressWarnings({"unchecked"})
328 public TreeZipper<C> f(final TreeZipper<A> ta, final TreeZipper<B> tb) {
329 final F2<Stream<Tree<A>>, Stream<Tree<B>>, Stream<Tree<C>>> sf = zipStreamM(treeM(f));
330 final
331 F2<Stream<P3<Stream<Tree<A>>, A, Stream<Tree<A>>>>,
332 Stream<P3<Stream<Tree<B>>, B, Stream<Tree<B>>>>,
333 Stream<P3<Stream<Tree<C>>, C, Stream<Tree<C>>>>>
334 pf =
335 zipStreamM(new F2<P3<Stream<Tree<A>>, A, Stream<Tree<A>>>,
336 P3<Stream<Tree<B>>, B, Stream<Tree<B>>>,
337 P3<Stream<Tree<C>>, C, Stream<Tree<C>>>>() {
338 public P3<Stream<Tree<C>>, C, Stream<Tree<C>>> f(final P3<Stream<Tree<A>>, A, Stream<Tree<A>>> pa,
339 final P3<Stream<Tree<B>>, B, Stream<Tree<B>>> pb) {
340 return p(zipStreamM(treeM(f)).f(pa._1(), pb._1()), f.f(pa._2(), pb._2()),
341 zipStreamM(treeM(f)).f(pa._3(), pb._3()));
342 }
343 });
344 return treeZipper(treeM(f).f(ta.p()._1(), tb.p()._1()), sf.f(ta.lefts(), tb.lefts()),
345 sf.f(ta.rights(), tb.rights()), pf.f(ta.p()._4(), tb.p()._4()));
346 }
347 };
348 }
349
350 static public <A, B, C, Z> F2<Z, B, C> contramapFirst(F2<A, B, C> target, F<Z, A> f) {
351 return (z, b) -> target.f(f.f(z), b);
352 }
353
354 static public <A, B, C, Z> F2<A, Z, C> contramapSecond(F2<A, B, C> target, F<Z, B> f) {
355 return (a, z) -> target.f(a, f.f(z));
356 }
357
358 static public <A, B, C, X, Y> F2<X, Y, C> contramap(F2<A, B, C> target, F<X, A> f, F<Y, B> g) {
359 return contramapSecond(contramapFirst(target, f), g);
360 }
361
362 static public <A, B, C, Z> F2<A, B, Z> map(F2<A, B, C> target, F<C, Z> f) {
363 return (a, b) -> f.f(target.f(a, b));
364 }
365
366 }