Skip to content

Commit 025587a

Browse files
committed
Merge branch 'optic-instances' of https://github.com/javafp/functionaljava into javafp-optic-instances
2 parents 1ba2f25 + a3407f6 commit 025587a

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
@@ -26,11 +26,21 @@
2626
import static fj.data.List.Buffer.*;
2727
import static fj.data.Option.none;
2828
import static fj.data.Option.some;
29+
import static fj.data.optic.Optional.optional;
30+
import static fj.data.optic.Prism.prism;
31+
import static fj.data.vector.V.v;
2932
import static fj.function.Booleans.not;
3033
import static fj.Ordering.GT;
3134
import static fj.Ord.intOrd;
3235
import fj.Ordering;
3336
import fj.control.Trampoline;
37+
import fj.control.parallel.Promise;
38+
import fj.control.parallel.Strategy;
39+
import fj.data.optic.Optional;
40+
import fj.data.optic.PTraversal;
41+
import fj.data.optic.Prism;
42+
import fj.data.optic.Traversal;
43+
import fj.data.vector.V2;
3444
import fj.function.Effect1;
3545

3646
import java.util.AbstractCollection;
@@ -608,6 +618,119 @@ public <B> IO<List<B>> traverseIO(F<A, IO<B>> f) {
608618
);
609619
}
610620

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

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

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

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

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

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)