Skip to content

Commit f0cbbb5

Browse files
committed
Adding composition guarantees to LensLike
1 parent b4ee3b8 commit f0cbbb5

File tree

4 files changed

+83
-51
lines changed

4 files changed

+83
-51
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
66
## [Unreleased]
77
### Added
88
- `Fn3-8` static factory overloads to aid in coercing lambdas
9+
- Adding composition guarantees to `LensLike`
910

1011
## [3.0.3] - 2018-05-27
1112
### Added

src/main/java/com/jnape/palatable/lambda/lens/Iso.java

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ default <Z> Iso<S, T, A, Z> mapB(Function<? super Z, ? extends B> fn) {
176176
return unIso().biMapR(f -> f.compose(fn)).into(Iso::iso);
177177
}
178178

179+
@Override
180+
default <C, D> Lens<S, T, C, D> andThen(LensLike<A, B, C, D, ?> f) {
181+
return toLens().andThen(f);
182+
}
183+
179184
/**
180185
* Left-to-right composition of {@link Iso}.
181186
*
@@ -200,6 +205,11 @@ default <Q, R> Iso<Q, R, A, B> compose(Iso<Q, R, S, T> g) {
200205
return g.andThen(this);
201206
}
202207

208+
@Override
209+
default <Q, R> Lens<Q, R, A, B> compose(LensLike<Q, R, S, T, ?> f) {
210+
return toLens().compose(f);
211+
}
212+
203213
/**
204214
* Static factory method for creating an iso from a function and it's inverse.
205215
*
@@ -243,23 +253,9 @@ static <S, A> Iso.Simple<S, A> simpleIso(Function<? super S, ? extends A> f, Fun
243253
* @param <S> the type of both "larger" values
244254
* @param <A> the type of both "smaller" values
245255
*/
256+
@FunctionalInterface
246257
interface Simple<S, A> extends Iso<S, S, A, A>, LensLike.Simple<S, A, Iso> {
247258

248-
@Override
249-
default Iso.Simple<A, S> mirror() {
250-
return adapt(Iso.super.mirror());
251-
}
252-
253-
@Override
254-
default Lens.Simple<S, A> toLens() {
255-
return Lens.Simple.adapt(Iso.super.toLens());
256-
}
257-
258-
@Override
259-
default <U> Iso.Simple<S, A> discardR(Applicative<U, LensLike<S, ?, A, A, Iso>> appB) {
260-
return adapt(Iso.super.discardR(appB));
261-
}
262-
263259
/**
264260
* Compose two simple isos from right to left.
265261
*
@@ -282,6 +278,31 @@ default <B> Iso.Simple<S, B> andThen(Iso.Simple<A, B> f) {
282278
return adapt(f.compose(this));
283279
}
284280

281+
@Override
282+
default Iso.Simple<A, S> mirror() {
283+
return adapt(Iso.super.mirror());
284+
}
285+
286+
@Override
287+
default Lens.Simple<S, A> toLens() {
288+
return Lens.Simple.adapt(Iso.super.toLens());
289+
}
290+
291+
@Override
292+
default <U> Iso.Simple<S, A> discardR(Applicative<U, LensLike<S, ?, A, A, Iso>> appB) {
293+
return adapt(Iso.super.discardR(appB));
294+
}
295+
296+
@Override
297+
default <R> Lens.Simple<R, A> compose(LensLike.Simple<R, S, ?> g) {
298+
return toLens().compose(g);
299+
}
300+
301+
@Override
302+
default <B> Lens.Simple<S, B> andThen(LensLike.Simple<A, B, ?> f) {
303+
return toLens().andThen(f);
304+
}
305+
285306
/**
286307
* Adapt an {@link Iso} with the right variance to an {@link Iso.Simple}.
287308
*

src/main/java/com/jnape/palatable/lambda/lens/Lens.java

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -220,27 +220,13 @@ default Iso<S, T, A, B> toIso(S s) {
220220
return iso(view(this), set(this).flip().apply(s));
221221
}
222222

223-
/**
224-
* Left-to-right composition of lenses. Requires compatibility between S and T.
225-
*
226-
* @param f the other lens
227-
* @param <C> the new "smaller" value to read (previously A)
228-
* @param <D> the new "smaller" update value (previously B)
229-
* @return the composed lens
230-
*/
231-
default <C, D> Lens<S, T, C, D> andThen(Lens<A, B, C, D> f) {
232-
return f.compose(this);
223+
@Override
224+
default <C, D> Lens<S, T, C, D> andThen(LensLike<A, B, C, D, ?> f) {
225+
return lens(view(this).fmap(view(f)), (q, b) -> over(this, set(f, b), q));
233226
}
234227

235-
/**
236-
* Right-to-left composition of lenses. Requires compatibility between A and B.
237-
*
238-
* @param g the other lens
239-
* @param <Q> the new "larger" value for reading (previously S)
240-
* @param <R> the new "larger" value for putting (previously T)
241-
* @return the composed lens
242-
*/
243-
default <Q, R> Lens<Q, R, A, B> compose(Lens<Q, R, S, T> g) {
228+
@Override
229+
default <Q, R> Lens<Q, R, A, B> compose(LensLike<Q, R, S, T, ?> g) {
244230
return lens(view(g).fmap(view(this)), (q, b) -> over(g, set(this, b), q));
245231
}
246232

@@ -323,26 +309,12 @@ static <S, A, B> Lens.Simple<S, Tuple2<A, B>> both(Lens.Simple<S, A> f, Lens.Sim
323309
@FunctionalInterface
324310
interface Simple<S, A> extends Lens<S, S, A, A>, LensLike.Simple<S, A, Lens> {
325311

326-
/**
327-
* Compose two simple lenses from right to left.
328-
*
329-
* @param g the other simple lens
330-
* @param <R> the other simple lens' larger type
331-
* @return the composed simple lens
332-
*/
333-
default <R> Lens.Simple<R, A> compose(Lens.Simple<R, S> g) {
312+
default <R> Lens.Simple<R, A> compose(LensLike.Simple<R, S, ?> g) {
334313
return Lens.Simple.adapt(Lens.super.compose(g));
335314
}
336315

337-
/**
338-
* Compose two simple lenses from left to right.
339-
*
340-
* @param f the other simple lens
341-
* @param <B> the other simple lens' smaller type
342-
* @return the composed simple lens
343-
*/
344-
default <B> Lens.Simple<S, B> andThen(Lens.Simple<A, B> f) {
345-
return f.compose(this);
316+
default <B> Lens.Simple<S, B> andThen(LensLike.Simple<A, B, ?> f) {
317+
return Lens.Simple.adapt(Lens.super.andThen(f));
346318
}
347319

348320
/**

src/main/java/com/jnape/palatable/lambda/lens/LensLike.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,26 @@ public interface LensLike<S, T, A, B, LL extends LensLike> extends Monad<T, Lens
2525
<F extends Functor, FT extends Functor<T, F>, FB extends Functor<B, F>> FT apply(
2626
Function<? super A, ? extends FB> fn, S s);
2727

28+
/**
29+
* Right-to-left composition of lenses. Requires compatibility between A and B.
30+
*
31+
* @param g the other lens
32+
* @param <Q> the new "larger" value for reading (previously S)
33+
* @param <R> the new "larger" value for putting (previously T)
34+
* @return the composed lens
35+
*/
36+
<Q, R> LensLike<Q, R, A, B, ?> compose(LensLike<Q, R, S, T, ?> g);
37+
38+
/**
39+
* Left-to-right composition of lenses. Requires compatibility between S and T.
40+
*
41+
* @param f the other lens
42+
* @param <C> the new "smaller" value to read (previously A)
43+
* @param <D> the new "smaller" update value (previously B)
44+
* @return the composed lens
45+
*/
46+
<C, D> LensLike<S, T, C, D, ?> andThen(LensLike<A, B, C, D, ?> f);
47+
2848
/**
2949
* Contravariantly map <code>S</code> to <code>R</code>, yielding a new lens.
3050
*
@@ -117,5 +137,23 @@ default <R> LensLike<R, T, A, B, LL> contraMap(Function<? super R, ? extends S>
117137
* @param <LL> the concrete lens subtype
118138
*/
119139
interface Simple<S, A, LL extends LensLike> extends LensLike<S, S, A, A, LL> {
140+
141+
/**
142+
* Compose two simple lenses from right to left.
143+
*
144+
* @param g the other simple lens
145+
* @param <R> the other simple lens' larger type
146+
* @return the composed simple lens
147+
*/
148+
<R> LensLike.Simple<R, A, ?> compose(LensLike.Simple<R, S, ?> g);
149+
150+
/**
151+
* Compose two simple lenses from left to right.
152+
*
153+
* @param f the other simple lens
154+
* @param <B> the other simple lens' smaller type
155+
* @return the composed simple lens
156+
*/
157+
<B> LensLike.Simple<S, B, ?> andThen(LensLike.Simple<A, B, ?> f);
120158
}
121159
}

0 commit comments

Comments
 (0)