Skip to content

Commit c591019

Browse files
committed
Make singletonHMap store the A instead of the B of TypeSafeKey.
Previously, HMap equality was broken for `singletonHMap` with custom keys.
1 parent 629000a commit c591019

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

src/main/java/com/jnape/palatable/lambda/adt/hmap/HMap.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ public static HMap emptyHMap() {
196196
* @return a singleton HMap
197197
*/
198198
public static <V> HMap singletonHMap(TypeSafeKey<?, V> key, V value) {
199-
return new HMap(singletonMap(key, value));
199+
return emptyHMap().put(key, value);
200200
}
201201

202202
/**
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.jnape.palatable.lambda.adt.hmap;
2+
3+
import com.jnape.palatable.lambda.functor.Functor;
4+
import com.jnape.palatable.lambda.functor.Profunctor;
5+
import com.jnape.palatable.lambda.lens.Iso;
6+
import org.junit.Test;
7+
8+
import java.math.BigInteger;
9+
import java.util.Objects;
10+
11+
import static com.jnape.palatable.lambda.adt.Maybe.just;
12+
import static com.jnape.palatable.lambda.adt.Maybe.nothing;
13+
import static com.jnape.palatable.lambda.adt.hmap.CustomTypeSafeKeyTest.CustomTypeSafeKey.customKey;
14+
import static com.jnape.palatable.lambda.adt.hmap.HMap.emptyHMap;
15+
import static com.jnape.palatable.lambda.adt.hmap.HMap.singletonHMap;
16+
import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id;
17+
import static java.math.BigInteger.ONE;
18+
import static org.junit.Assert.assertEquals;
19+
20+
public class CustomTypeSafeKeyTest {
21+
22+
public static class CustomTypeSafeKey<T> implements TypeSafeKey<String, T> {
23+
int tag;
24+
Iso.Simple<String, T> iso;
25+
26+
private CustomTypeSafeKey(int tag, Iso.Simple<String, T> iso) {
27+
this.tag = tag;
28+
this.iso = iso;
29+
}
30+
31+
@Override
32+
public <P extends Profunctor, F extends Functor, FB extends Functor<T, F>, FT extends Functor<String, F>, PAFB extends Profunctor<T, FB, P>, PSFT extends Profunctor<String, FT, P>> PSFT apply(PAFB pafb) {
33+
return iso.<P, F, FB, FT, PAFB, PSFT>apply(pafb);
34+
}
35+
36+
@Override
37+
public boolean equals(Object o) {
38+
if (this == o) return true;
39+
if (o == null || getClass() != o.getClass()) return false;
40+
CustomTypeSafeKey<?> customTypeSafeKey = (CustomTypeSafeKey<?>) o;
41+
return Objects.equals(tag, customTypeSafeKey.tag);
42+
}
43+
44+
@Override
45+
public int hashCode() {
46+
return Objects.hash(tag);
47+
}
48+
49+
static <T> CustomTypeSafeKey<T> customKey(int tag, Iso.Simple<String, T> iso) {
50+
return new CustomTypeSafeKey<>(tag, iso);
51+
}
52+
53+
static CustomTypeSafeKey<String> customKey(int tag) {
54+
return customKey(tag, Iso.simpleIso(id(), id()));
55+
}
56+
}
57+
58+
private static final Iso.Simple<String, Long> STRING_TO_LONG = Iso.simpleIso(Long::parseLong, String::valueOf);
59+
private static final Iso.Simple<Long, BigInteger> LONG_TO_BIG_INTEGER = Iso.simpleIso(BigInteger::valueOf, BigInteger::longValue);
60+
61+
private static final CustomTypeSafeKey<String> KEY_1_AS_STRING = CustomTypeSafeKey.customKey(1);
62+
private static final CustomTypeSafeKey<String> KEY_1_AS_STRING_AGAIN = CustomTypeSafeKey.customKey(1);
63+
private static final CustomTypeSafeKey<Long> KEY_1_AS_LONG = customKey(1, STRING_TO_LONG);
64+
private static final CustomTypeSafeKey<BigInteger> KEY_1_AS_BIG_INTEGER = customKey(1, STRING_TO_LONG.andThen(LONG_TO_BIG_INTEGER));
65+
66+
@Test
67+
public void getDifferentViewsOfSameKey() {
68+
HMap hMap = singletonHMap(KEY_1_AS_STRING, "1");
69+
assertEquals(just("1"), hMap.get(KEY_1_AS_STRING));
70+
assertEquals(just("1"), hMap.get(KEY_1_AS_STRING_AGAIN));
71+
assertEquals(just(1L), hMap.get(KEY_1_AS_LONG));
72+
assertEquals(just(ONE), hMap.get(KEY_1_AS_BIG_INTEGER));
73+
assertEquals(nothing(), hMap.get(customKey(2)));
74+
}
75+
76+
@Test
77+
public void putStoresA() {
78+
assertEquals(emptyHMap().put(KEY_1_AS_STRING, "1"), emptyHMap().put(KEY_1_AS_LONG, 1L));
79+
assertEquals(emptyHMap().put(KEY_1_AS_STRING, "1"), emptyHMap().put(KEY_1_AS_BIG_INTEGER, ONE));
80+
}
81+
82+
@Test
83+
public void singletonHMapStoresA() {
84+
assertEquals(singletonHMap(KEY_1_AS_STRING, "1"), singletonHMap(KEY_1_AS_LONG, 1L));
85+
assertEquals(singletonHMap(KEY_1_AS_STRING, "1"), singletonHMap(KEY_1_AS_BIG_INTEGER, ONE));
86+
}
87+
}

0 commit comments

Comments
 (0)