Skip to content

Commit e080f28

Browse files
committed
Adding Under, the inverse of Over for Isos
1 parent 92db2a3 commit e080f28

3 files changed

Lines changed: 75 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
3636
- `Exchange`, a `Profunctor` that can extract the morphisms from an `Iso`
3737
- `HMapLens`, lenses focusing on `HMap`
3838
- `MapLens#mappingValues(Iso)`, a lawful lens that maps the values of a `j.u.Map`
39+
- `Under`, the inverse of `Over` for `Iso`
3940

4041
### Deprecated
4142
- `MapLens#mappingValues(Function)` is now deprecated in favor of the overload that takes an <code>Iso</code>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.jnape.palatable.lambda.lens.functions;
2+
3+
import com.jnape.palatable.lambda.functions.Fn1;
4+
import com.jnape.palatable.lambda.functions.Fn2;
5+
import com.jnape.palatable.lambda.functions.Fn3;
6+
import com.jnape.palatable.lambda.lens.Iso;
7+
import com.jnape.palatable.lambda.lens.LensLike;
8+
9+
import java.util.function.Function;
10+
11+
/**
12+
* The inverse of {@link Over}: given an {@link Iso}, a function from <code>T</code> to <code>S</code>, and a "smaller"
13+
* value <code>B</code>, return a "smaller" value <code>A</code> by traversing around the type ring (<code>B -&gt; T
14+
* -&gt; S -&gt; A</code>).
15+
* <p>
16+
* Note this is only possible for {@link Iso}s and not general {@link LensLike}s because of the mandatory need for the
17+
* correspondence <code>B -&gt; T</code>.
18+
*
19+
* @param <S> the larger type for focusing
20+
* @param <T> the larger type for mirrored focusing
21+
* @param <A> the smaller type for focusing
22+
* @param <B> the smaller type for mirrored focusing
23+
*/
24+
public final class Under<S, T, A, B> implements Fn3<Iso<S, T, A, B>, Function<? super T, ? extends S>, B, A> {
25+
26+
private static final Under INSTANCE = new Under();
27+
28+
private Under() {
29+
}
30+
31+
@Override
32+
public A apply(Iso<S, T, A, B> iso, Function<? super T, ? extends S> fn, B b) {
33+
return iso.unIso().into((sa, bt) -> bt.fmap(fn).fmap(sa)).apply(b);
34+
}
35+
36+
@SuppressWarnings("unchecked")
37+
public static <S, T, A, B> Under<S, T, A, B> under() {
38+
return INSTANCE;
39+
}
40+
41+
public static <S, T, A, B> Fn2<Function<? super T, ? extends S>, B, A> under(Iso<S, T, A, B> iso) {
42+
return Under.<S, T, A, B>under().apply(iso);
43+
}
44+
45+
public static <S, T, A, B> Fn1<B, A> under(Iso<S, T, A, B> iso, Function<? super T, ? extends S> fn) {
46+
return under(iso).apply(fn);
47+
}
48+
49+
public static <S, T, A, B> A under(Iso<S, T, A, B> iso, Function<? super T, ? extends S> fn, B b) {
50+
return under(iso, fn).apply(b);
51+
}
52+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.jnape.palatable.lambda.lens.functions;
2+
3+
import com.jnape.palatable.lambda.lens.Iso;
4+
import org.junit.Test;
5+
6+
import java.util.Collections;
7+
import java.util.List;
8+
import java.util.Set;
9+
10+
import static com.jnape.palatable.lambda.lens.Iso.iso;
11+
import static com.jnape.palatable.lambda.lens.functions.Under.under;
12+
import static java.util.Collections.singletonList;
13+
import static org.junit.Assert.assertEquals;
14+
15+
public class UnderTest {
16+
17+
@Test
18+
public void reversesTypeRingWalk() {
19+
Iso<List<String>, Set<Integer>, String, Integer> iso = iso(xs -> xs.get(0), Collections::singleton);
20+
assertEquals("1", under(iso, set -> singletonList(set.iterator().next().toString()), 1));
21+
}
22+
}

0 commit comments

Comments
 (0)