Mercurial > hg > Members > tatsuki > functionaljava-master > core
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 } |