Skip to content

Commit 9266c2a

Browse files
committed
Merge branch 'javafp-optic-instances'
2 parents fe5c13c + 025587a commit 9266c2a

File tree

17 files changed

+419
-46
lines changed

17 files changed

+419
-46
lines changed

core/src/main/java/fj/P2.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package fj;
22

33
import static fj.Function.*;
4-
4+
import static fj.data.optic.PLens.pLens;
55
import fj.data.*;
6+
import fj.data.optic.Lens;
7+
import fj.data.optic.PLens;
68

79
/**
810
* A product-2.
@@ -342,6 +344,34 @@ public static <A, B, C> F2<A, B, C> untuple(final F<P2<A, B>, C> f) {
342344
return (a, b) -> f.f(P.p(a, b));
343345
}
344346

347+
/**
348+
* Polyomorphic lens targeted on _1.
349+
*/
350+
public static <A, B, C> PLens<P2<A, B>, P2<C, B>, A, C> _1pLens() {
351+
return pLens(__1(), a -> p2 -> P.p(a, p2._2()));
352+
}
353+
354+
/**
355+
* Monomorphic lens targeted on _1.
356+
*/
357+
public static <A, B, C> Lens<P2<A, B>, A> _1Lens() {
358+
return new Lens<>(_1pLens());
359+
}
360+
361+
/**
362+
* Polyomorphic lens targeted on _2.
363+
*/
364+
public static <A, B, C> PLens<P2<A, B>, P2<A, C>, B, C> _2pLens() {
365+
return pLens(__2(), b -> p2 -> P.p(p2._1(), b));
366+
}
367+
368+
/**
369+
* Monomorphic lens targeted on _1.
370+
*/
371+
public static <A, B, C> Lens<P2<A, B>, B> _2Lens() {
372+
return new Lens<>(_2pLens());
373+
}
374+
345375
@Override
346376
public String toString() {
347377
return Show.p2Show(Show.<A>anyShow(), Show.<B>anyShow()).showS(this);

core/src/main/java/fj/data/List.java

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,21 @@
2424
import static fj.data.List.Buffer.*;
2525
import static fj.data.Option.none;
2626
import static fj.data.Option.some;
27+
import static fj.data.optic.Optional.optional;
28+
import static fj.data.optic.Prism.prism;
29+
import static fj.data.vector.V.v;
2730
import static fj.function.Booleans.not;
2831
import static fj.Ordering.GT;
2932
import static fj.Ord.intOrd;
3033
import fj.Ordering;
3134
import fj.control.Trampoline;
35+
import fj.control.parallel.Promise;
36+
import fj.control.parallel.Strategy;
37+
import fj.data.optic.Optional;
38+
import fj.data.optic.PTraversal;
39+
import fj.data.optic.Prism;
40+
import fj.data.optic.Traversal;
41+
import fj.data.vector.V2;
3242
import fj.function.Effect1;
3343

3444
import java.util.AbstractCollection;
@@ -607,6 +617,119 @@ public <B> IO<List<B>> traverseIO(F<A, IO<B>> f) {
607617
);
608618
}
609619

620+
public <C, B> F<C, List<B>> traverseF(F<A, F<C, B>> f) {
621+
return this.foldRight(
622+
(a, acc) -> Function.bind(acc,
623+
(bs) -> Function.<C, B, List<B>> compose(b -> bs.cons(b), f.f(a))),
624+
Function.constant(List.<B> nil())
625+
);
626+
}
627+
628+
public <B> Trampoline<List<B>> traverseTrampoline(final F<A, Trampoline<B>> f) {
629+
return foldRight(
630+
(a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))),
631+
Trampoline.pure(List.<B> nil()));
632+
}
633+
634+
public <B> Promise<List<B>> traversePromise(final F<A, Promise<B>> f) {
635+
return foldRight(
636+
(a, acc) -> f.f(a).bind(b -> acc.fmap(bs -> bs.cons(b))),
637+
Promise.promise(Strategy.idStrategy(), p(List.<B> nil())));
638+
}
639+
640+
public <B> List<List<B>> traverseList(final F<A, List<B>> f) {
641+
return foldRight(
642+
(a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))),
643+
List.single(List.<B> nil()));
644+
}
645+
646+
public <E, B> Validation<E, List<B>> traverseValidation(final F<A, Validation<E, B>> f) {
647+
return foldRight(
648+
(a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))),
649+
Validation.success(List.<B> nil()));
650+
}
651+
652+
public <B> V2<List<B>> traverseV2(final F<A, V2<B>> f) {
653+
return foldRight(
654+
(a, acc) -> acc.apply(f.f(a).<F<List<B>, List<B>>> map(e -> es -> es.cons(e))),
655+
v(List.<B> nil(), List.<B> nil()));
656+
}
657+
658+
/**
659+
* polymorphic traversal
660+
*/
661+
public static <A, B> PTraversal<List<A>, List<B>, A, B> _pTraversal() {
662+
return new PTraversal<List<A>, List<B>, A, B>() {
663+
664+
@Override
665+
public <C> F<List<A>, F<C, List<B>>> modifyFunctionF(F<A, F<C, B>> f) {
666+
return l -> l.traverseF(f);
667+
}
668+
669+
@Override
670+
public <L> F<List<A>, Either<L, List<B>>> modifyEitherF(F<A, Either<L, B>> f) {
671+
return l -> l.traverseEither(f);
672+
}
673+
674+
@Override
675+
public F<List<A>, IO<List<B>>> modifyIOF(F<A, IO<B>> f) {
676+
return l -> l.traverseIO(f);
677+
}
678+
679+
@Override
680+
public F<List<A>, Trampoline<List<B>>> modifyTrampolineF(F<A, Trampoline<B>> f) {
681+
return l -> l.traverseTrampoline(f);
682+
}
683+
684+
@Override
685+
public F<List<A>, Promise<List<B>>> modifyPromiseF(F<A, Promise<B>> f) {
686+
return l -> l.traversePromise(f);
687+
}
688+
689+
@Override
690+
public F<List<A>, List<List<B>>> modifyListF(F<A, List<B>> f) {
691+
return l -> l.traverseList(f);
692+
}
693+
694+
@Override
695+
public F<List<A>, Option<List<B>>> modifyOptionF(F<A, Option<B>> f) {
696+
return l -> l.traverseOption(f);
697+
}
698+
699+
@Override
700+
public F<List<A>, Stream<List<B>>> modifyStreamF(F<A, Stream<B>> f) {
701+
return l -> l.traverseStream(f);
702+
}
703+
704+
@Override
705+
public F<List<A>, P1<List<B>>> modifyP1F(F<A, P1<B>> f) {
706+
return l -> l.traverseP1(f);
707+
}
708+
709+
@Override
710+
public <E> F<List<A>, Validation<E, List<B>>> modifyValidationF(F<A, Validation<E, B>> f) {
711+
return l -> l.traverseValidation(f);
712+
}
713+
714+
@Override
715+
public F<List<A>, V2<List<B>>> modifyV2F(F<A, V2<B>> f) {
716+
return l -> l.traverseV2(f);
717+
}
718+
719+
@Override
720+
public <M> F<List<A>, M> foldMap(Monoid<M> monoid, F<A, M> f) {
721+
return l -> monoid.sumLeft(l.map(f));
722+
}
723+
};
724+
}
725+
726+
/**
727+
* monomorphic traversal
728+
*/
729+
public static <A> Traversal<List<A>, A> _traversal() {
730+
return new Traversal<>(_pTraversal());
731+
}
732+
610733
/**
611734
* Performs function application within a list (applicative functor pattern).
612735
*
@@ -1053,6 +1176,13 @@ public final List<A> nub(final Ord<A> o) {
10531176
return sort(o).group(o.equal()).map(List.<A>head_());
10541177
}
10551178

1179+
/**
1180+
* Optional targeted on Cons head.
1181+
*/
1182+
public static <A> Optional<List<A>, A> _head() {
1183+
return optional(l -> l.toOption(), a -> l -> l.<List<A>> list(l, constant(cons_(a))));
1184+
}
1185+
10561186
/**
10571187
* First-class head function.
10581188
*
@@ -1062,6 +1192,14 @@ public static <A> F<List<A>, A> head_() {
10621192
return list -> list.head();
10631193
}
10641194

1195+
/**
1196+
* Optional targeted on Cons tail.
1197+
*/
1198+
public static <A> Optional<List<A>, List<A>> _tail() {
1199+
return optional(l -> l.<Option<List<A>>> list(none(), h -> tail -> some(tail)),
1200+
tail -> l -> l.list(l, h -> constant(cons(h, tail))));
1201+
}
1202+
10651203
/**
10661204
* First-class tail function.
10671205
*
@@ -1459,6 +1597,13 @@ public static <A> List<A> nil() {
14591597
return (Nil<A>) Nil.INSTANCE;
14601598
}
14611599

1600+
/**
1601+
* Nil prism
1602+
*/
1603+
public static <A> Prism<List<A>, Unit> _nil() {
1604+
return prism(l -> l.isEmpty() ? some(unit()) : none(), constant(nil()));
1605+
}
1606+
14621607
/**
14631608
* Returns a function that prepends (cons) an element to a list to produce a new list.
14641609
*
@@ -1468,6 +1613,13 @@ public static <A> F<A, F<List<A>, List<A>>> cons() {
14681613
return a -> tail -> cons(a, tail);
14691614
}
14701615

1616+
/**
1617+
* Cons prism
1618+
*/
1619+
public static <A> Prism<List<A>, P2<A, List<A>>> _cons() {
1620+
return prism(l -> l.<Option<P2<A, List<A>>>> list(none(), h -> tail -> some(P.p(h, tail))), c -> cons(c._1(), c._2()));
1621+
}
1622+
14711623
public static <A> F2<A, List<A>, List<A>> cons_() {
14721624
return (a, listA) -> cons(a, listA);
14731625
}

core/src/main/java/fj/data/optic/Fold.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public final F<S, Option<A>> find(final F<A, Boolean> p) {
4444

4545
/** get the first target of a {@link Fold} */
4646
public final Option<A> headOption(final S s) {
47-
return find(__ -> true).f(s);
47+
return find(Function.constant(Boolean.TRUE)).f(s);
4848
}
4949

5050
/** check if at least one target satisfies the predicate */

core/src/main/java/fj/data/optic/Optional.java

Lines changed: 117 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
package fj.data.optic;
22

33
import fj.F;
4+
import fj.Function;
5+
import fj.P;
46
import fj.P1;
57
import fj.P2;
68
import fj.control.Trampoline;
79
import fj.control.parallel.Promise;
10+
import fj.control.parallel.Strategy;
811
import fj.data.Either;
912
import fj.data.IO;
13+
import fj.data.IOFunctions;
1014
import fj.data.List;
1115
import fj.data.Option;
1216
import fj.data.Stream;
1317
import fj.data.Validation;
18+
import fj.data.vector.V;
1419
import fj.data.vector.V2;
1520

1621
/** {@link POptional} restricted to monomorphic update */
@@ -166,9 +171,118 @@ public static <S> Optional<S, S> id() {
166171
return new Optional<>(POptional.pId());
167172
}
168173

169-
/** create a {@link Optional} using the canonical functions: getOrModify and set */
170-
public static final <S, A> Optional<S, A> optional(final F<S, Either<S, A>> getOrModify, final F<A, F<S, S>> set) {
171-
return new Optional<>(POptional.pOptional(getOrModify, set));
174+
public static final <S, A> Optional<S, A> optional(final F<S, Option<A>> getOption, final F<A, F<S, S>> set) {
175+
return new Optional<>(new POptional<S, S, A, A>() {
176+
177+
@Override
178+
public Either<S, A> getOrModify(final S s) {
179+
return getOption.f(s).option(Either.left(s), Either.<S, A> right_());
180+
}
181+
182+
@Override
183+
public F<S, S> set(final A a) {
184+
return set.f(a);
185+
}
186+
187+
@Override
188+
public Option<A> getOption(final S s) {
189+
return getOption.f(s);
190+
}
191+
192+
@Override
193+
public <C> F<S, F<C, S>> modifyFunctionF(final F<A, F<C, A>> f) {
194+
return s -> getOption.f(s).<F<C, S>> option(
195+
(C __) -> s,
196+
a -> Function.compose(b -> set.f(b).f(s), f.f(a))
197+
);
198+
}
199+
200+
@Override
201+
public <L> F<S, Either<L, S>> modifyEitherF(final F<A, Either<L, A>> f) {
202+
return s -> getOption.f(s).<Either<L, S>> option(
203+
Either.right(s),
204+
t -> f.f(t).right().map(b -> set.f(b).f(s))
205+
);
206+
}
207+
208+
@Override
209+
public F<S, IO<S>> modifyIOF(final F<A, IO<A>> f) {
210+
return s -> getOption.f(s).option(
211+
IOFunctions.unit(s),
212+
a -> IOFunctions.<A, S> map(f.f(a), b -> set.f(b).f(s))
213+
);
214+
}
215+
216+
@Override
217+
public F<S, Trampoline<S>> modifyTrampolineF(final F<A, Trampoline<A>> f) {
218+
return s -> getOption.f(s).option(
219+
Trampoline.pure(s),
220+
t -> f.f(t).map(b -> set.f(b).f(s))
221+
);
222+
}
223+
224+
@Override
225+
public F<S, Promise<S>> modifyPromiseF(final F<A, Promise<A>> f) {
226+
return s -> getOption.f(s).<Promise<S>> option(
227+
() -> Promise.promise(Strategy.idStrategy(), P.p(s)),
228+
t -> f.f(t).fmap(b -> set.f(b).f(s))
229+
);
230+
}
231+
232+
@Override
233+
public F<S, List<S>> modifyListF(final F<A, List<A>> f) {
234+
return s -> getOption.f(s).<List<S>> option(
235+
() -> List.single(s),
236+
t -> f.f(t).map(b -> set.f(b).f(s))
237+
);
238+
}
239+
240+
@Override
241+
public F<S, Option<S>> modifyOptionF(final F<A, Option<A>> f) {
242+
return s -> getOption.f(s).option(
243+
Option.some(s),
244+
t -> f.f(t).map(b -> set.f(b).f(s))
245+
);
246+
}
247+
248+
@Override
249+
public F<S, Stream<S>> modifyStreamF(final F<A, Stream<A>> f) {
250+
return s -> getOption.f(s).<Stream<S>> option(
251+
() -> Stream.single(s),
252+
t -> f.f(t).map(b -> set.f(b).f(s))
253+
);
254+
}
255+
256+
@Override
257+
public F<S, P1<S>> modifyP1F(final F<A, P1<A>> f) {
258+
return s -> getOption.f(s).<P1<S>> option(
259+
P.p(s),
260+
t -> f.f(t).map(b -> set.f(b).f(s))
261+
);
262+
}
263+
264+
@Override
265+
public <E> F<S, Validation<E, S>> modifyValidationF(final F<A, Validation<E, A>> f) {
266+
return s -> getOption.f(s).<Validation<E, S>> option(
267+
() -> Validation.<E, S> success(s),
268+
t -> f.f(t).map(b -> set.f(b).f(s))
269+
);
270+
}
271+
272+
@Override
273+
public F<S, V2<S>> modifyV2F(final F<A, V2<A>> f) {
274+
return s -> getOption.f(s).<V2<S>> option(
275+
() -> V.v(s, s),
276+
t -> f.f(t).map(b -> set.f(b).f(s))
277+
);
278+
}
279+
280+
@Override
281+
public F<S, S> modify(final F<A, A> f) {
282+
return s -> getOption.f(s).option(s, a -> set.f(f.f(a)).f(s));
283+
}
284+
285+
});
172286
}
173287

174288
}

0 commit comments

Comments
 (0)