Skip to content

Commit 48ca232

Browse files
committed
Schema, for representing TSK schemas in HMaps
1 parent e8f1888 commit 48ca232

File tree

4 files changed

+147
-3
lines changed

4 files changed

+147
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
77
### Added
88
- `Lens#toIso`, for converting a lens to an iso
99
- `HMap#hMap` overloads up to 8 bindings deep
10+
- `Schema`, schemas for extracting multiple values from `HMap`s by aggregating `TypeSafeKey`s
1011

1112
### Fixed
1213
- Deforested iterables execute in intended nesting order, where essential
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package com.jnape.palatable.lambda.adt.hmap;
2+
3+
import com.jnape.palatable.lambda.adt.Maybe;
4+
import com.jnape.palatable.lambda.adt.hlist.HList;
5+
import com.jnape.palatable.lambda.adt.hlist.HList.HCons;
6+
import com.jnape.palatable.lambda.adt.hlist.SingletonHList;
7+
import com.jnape.palatable.lambda.adt.hlist.Tuple2;
8+
import com.jnape.palatable.lambda.adt.hlist.Tuple3;
9+
import com.jnape.palatable.lambda.adt.hlist.Tuple4;
10+
import com.jnape.palatable.lambda.adt.hlist.Tuple5;
11+
import com.jnape.palatable.lambda.adt.hlist.Tuple6;
12+
import com.jnape.palatable.lambda.adt.hlist.Tuple7;
13+
import com.jnape.palatable.lambda.adt.hlist.Tuple8;
14+
import com.jnape.palatable.lambda.functions.builtin.fn2.Both;
15+
import com.jnape.palatable.lambda.lens.Lens;
16+
17+
import static com.jnape.palatable.lambda.functions.builtin.fn2.Into.into;
18+
import static com.jnape.palatable.lambda.lens.lenses.HMapLens.valueAt;
19+
20+
public interface Schema<Values extends HCons<?, ?>> extends Lens.Simple<HMap, Maybe<Values>> {
21+
22+
@SuppressWarnings("unchecked")
23+
default <A, NewValues extends HCons<A, Values>> Schema<NewValues> add(TypeSafeKey<?, A> key) {
24+
return Lens.both(this, valueAt(key))
25+
.<Maybe<NewValues>>mapA(into((maybeValues, maybeA) -> maybeValues.zip(maybeA.fmap(a -> values -> (NewValues) values.cons(a)))))
26+
.<Maybe<NewValues>>mapB(Both.both(maybeNewValues -> maybeNewValues.fmap(HCons::tail),
27+
maybeNewValues -> maybeNewValues.fmap(HCons::head)))
28+
::apply;
29+
}
30+
31+
static <A> Schema<SingletonHList<A>> schema(TypeSafeKey<?, A> key) {
32+
return valueAt(key)
33+
.mapA(ma -> ma.fmap(HList::singletonHList))
34+
.<Maybe<SingletonHList<A>>>mapB(maybeSingletonA -> maybeSingletonA.fmap(HCons::head))
35+
::apply;
36+
}
37+
38+
static <A, B> Schema<Tuple2<A, B>> schema(TypeSafeKey<?, A> aKey,
39+
TypeSafeKey<?, B> bKey) {
40+
return schema(bKey).add(aKey);
41+
}
42+
43+
static <A, B, C> Schema<Tuple3<A, B, C>> schema(TypeSafeKey<?, A> aKey,
44+
TypeSafeKey<?, B> bKey,
45+
TypeSafeKey<?, C> cKey) {
46+
return schema(bKey, cKey).add(aKey);
47+
}
48+
49+
static <A, B, C, D> Schema<Tuple4<A, B, C, D>> schema(TypeSafeKey<?, A> aKey,
50+
TypeSafeKey<?, B> bKey,
51+
TypeSafeKey<?, C> cKey,
52+
TypeSafeKey<?, D> dKey) {
53+
return schema(bKey, cKey, dKey).add(aKey);
54+
}
55+
56+
57+
static <A, B, C, D, E> Schema<Tuple5<A, B, C, D, E>> schema(TypeSafeKey<?, A> aKey,
58+
TypeSafeKey<?, B> bKey,
59+
TypeSafeKey<?, C> cKey,
60+
TypeSafeKey<?, D> dKey,
61+
TypeSafeKey<?, E> eKey) {
62+
return schema(bKey, cKey, dKey, eKey).add(aKey);
63+
}
64+
65+
static <A, B, C, D, E, F> Schema<Tuple6<A, B, C, D, E, F>> schema(TypeSafeKey<?, A> aKey,
66+
TypeSafeKey<?, B> bKey,
67+
TypeSafeKey<?, C> cKey,
68+
TypeSafeKey<?, D> dKey,
69+
TypeSafeKey<?, E> eKey,
70+
TypeSafeKey<?, F> fKey) {
71+
return schema(bKey, cKey, dKey, eKey, fKey).add(aKey);
72+
}
73+
74+
static <A, B, C, D, E, F, G> Schema<Tuple7<A, B, C, D, E, F, G>> schema(TypeSafeKey<?, A> aKey,
75+
TypeSafeKey<?, B> bKey,
76+
TypeSafeKey<?, C> cKey,
77+
TypeSafeKey<?, D> dKey,
78+
TypeSafeKey<?, E> eKey,
79+
TypeSafeKey<?, F> fKey,
80+
TypeSafeKey<?, G> gKey) {
81+
return schema(bKey, cKey, dKey, eKey, fKey, gKey).add(aKey);
82+
}
83+
84+
static <A, B, C, D, E, F, G, H> Schema<Tuple8<A, B, C, D, E, F, G, H>> schema(TypeSafeKey<?, A> aKey,
85+
TypeSafeKey<?, B> bKey,
86+
TypeSafeKey<?, C> cKey,
87+
TypeSafeKey<?, D> dKey,
88+
TypeSafeKey<?, E> eKey,
89+
TypeSafeKey<?, F> fKey,
90+
TypeSafeKey<?, G> gKey,
91+
TypeSafeKey<?, H> hKey) {
92+
return schema(bKey, cKey, dKey, eKey, fKey, gKey, hKey).add(aKey);
93+
}
94+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.jnape.palatable.lambda.adt.hmap;
2+
3+
import org.junit.Test;
4+
5+
import static com.jnape.palatable.lambda.adt.Maybe.just;
6+
import static com.jnape.palatable.lambda.adt.Maybe.nothing;
7+
import static com.jnape.palatable.lambda.adt.hlist.HList.tuple;
8+
import static com.jnape.palatable.lambda.adt.hmap.HMap.emptyHMap;
9+
import static com.jnape.palatable.lambda.adt.hmap.HMap.hMap;
10+
import static com.jnape.palatable.lambda.adt.hmap.Schema.schema;
11+
import static com.jnape.palatable.lambda.adt.hmap.TypeSafeKey.typeSafeKey;
12+
import static com.jnape.palatable.lambda.lens.functions.View.view;
13+
import static java.util.Arrays.asList;
14+
import static org.junit.Assert.assertEquals;
15+
import static testsupport.assertion.LensAssert.assertLensLawfulness;
16+
17+
public class SchemaTest {
18+
19+
@Test
20+
public void extractsValuesAtKeysFromMap() {
21+
TypeSafeKey.Simple<Byte> byteKey = typeSafeKey();
22+
TypeSafeKey.Simple<Short> shortKey = typeSafeKey();
23+
TypeSafeKey.Simple<Integer> intKey = typeSafeKey();
24+
TypeSafeKey.Simple<Long> longKey = typeSafeKey();
25+
TypeSafeKey.Simple<Float> floatKey = typeSafeKey();
26+
TypeSafeKey.Simple<Double> doubleKey = typeSafeKey();
27+
TypeSafeKey.Simple<Character> charKey = typeSafeKey();
28+
TypeSafeKey.Simple<Boolean> booleanKey = typeSafeKey();
29+
30+
HMap m = hMap(byteKey, (byte) 1,
31+
shortKey, (short) 2,
32+
intKey, 3,
33+
longKey, 4L,
34+
floatKey, 5F,
35+
doubleKey, 6D,
36+
charKey, '7',
37+
booleanKey, true);
38+
39+
assertLensLawfulness(schema(byteKey, shortKey, intKey, longKey, floatKey, doubleKey, charKey, booleanKey),
40+
asList(emptyHMap(),
41+
m),
42+
asList(nothing(),
43+
just(tuple((byte) 1, (short) 2, 3, 4L, 5F, 6D, '7', true))));
44+
}
45+
46+
@Test
47+
public void extractsNothingIfAnyKeysMissing() {
48+
assertEquals(nothing(), view(schema(typeSafeKey()), emptyHMap()));
49+
}
50+
}

src/test/java/com/jnape/palatable/lambda/functions/recursion/TrampolineTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
package com.jnape.palatable.lambda.functions.recursion;
22

33
import com.jnape.palatable.lambda.adt.hlist.Tuple2;
4-
import com.jnape.palatable.lambda.functions.recursion.RecursiveResult;
54
import org.junit.Test;
65

76
import java.math.BigInteger;
87
import java.util.function.Function;
98

109
import static com.jnape.palatable.lambda.adt.hlist.HList.tuple;
1110
import static com.jnape.palatable.lambda.functions.builtin.fn2.Into.into;
12-
import static java.math.BigInteger.ONE;
13-
import static org.junit.Assert.assertEquals;
1411
import static com.jnape.palatable.lambda.functions.recursion.RecursiveResult.recurse;
1512
import static com.jnape.palatable.lambda.functions.recursion.RecursiveResult.terminate;
1613
import static com.jnape.palatable.lambda.functions.recursion.Trampoline.trampoline;
14+
import static java.math.BigInteger.ONE;
15+
import static org.junit.Assert.assertEquals;
1716

1817
public class TrampolineTest {
1918

0 commit comments

Comments
 (0)