Skip to content

Instantly share code, notes, and snippets.

@cboudereau
Last active September 10, 2023 08:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cboudereau/4e4668cb7ceac2c65ec5e9571f20e7dd to your computer and use it in GitHub Desktop.
Save cboudereau/4e4668cb7ceac2c65ec5e9571f20e7dd to your computer and use it in GitHub Desktop.
ord trait java adt (rust backport)
package com.adt;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
public class AdtTest {
sealed interface Value<T extends Comparable<T>> extends Comparable<Value<T>> permits Value.Fixed, Value.Infinite {
static record Tuple<L, R>(L fst, R snd) {
}
public static final record Fixed<T extends Comparable<T>>(T value) implements Value<T> {
}
public static final record Infinite<T extends Comparable<T>>() implements Value<T> {
}
public static <T extends Comparable<T>> Fixed<T> fixed(final T value) {
return new Fixed<>(value);
}
public static <T extends Comparable<T>> Infinite<T> infinite() {
return new Infinite<>();
}
@Override
default int compareTo(final Value<T> o) {
return switch (new Tuple<>(this, o)) {
case Tuple<Value<T>, Value<T>>(Value.Infinite<T> fst, Value.Infinite<T> snd) -> 0;
case Tuple<Value<T>, Value<T>>(Value.Infinite<T> fst, Value.Fixed<T> snd) -> 1;
case Tuple<Value<T>, Value<T>>(Value.Fixed<T> fst, Value.Infinite<T> snd) -> -1;
case Tuple<Value<T>, Value<T>>(Value.Fixed<T> fst, Value.Fixed<T> snd) ->
fst.value.compareTo(snd.value);
};
}
default boolean isGreaterThan(final Value<T> o) {
return this.compareTo(o) > 0;
}
default boolean isLessThan(final Value<T> o) {
return this.compareTo(o) < 0;
}
}
@Test
public void compareToTest() {
assertEquals(0, Value.infinite().compareTo(Value.infinite()));
assertEquals(0, Value.fixed(1).compareTo(Value.fixed(1)));
assertTrue(Value.fixed(1).isLessThan(Value.infinite()));
assertTrue(Value.fixed(2).isGreaterThan(Value.fixed(1)));
assertTrue(Value.fixed(1).isLessThan(Value.fixed(2)));
}
}
@cboudereau
Copy link
Author

I finally got the trick to simplify the pattern matching switch expression by using a product pattern matching but still, it is required to add a default case even if it is totally covered : https://gist.github.com/cboudereau/4e4668cb7ceac2c65ec5e9571f20e7dd#file-adtordtest-java-L36

@cboudereau
Copy link
Author

cboudereau commented Sep 8, 2023

It looks like that the https://openjdk.org/jeps/441 is not solving the issue with the latest preview of java 21 and still have "A switch expression should have a default case" error when trying to remove the useless default case

Here is an interesting discussion on amber-dev : https://mail.openjdk.org/pipermail/amber-dev/2023-May/008076.html

Bug tracker : https://bugs.openjdk.org/browse/JDK-8300542

@cboudereau
Copy link
Author

There is also jacoco exhaustiveness issue already tracked : jacoco/jacoco#1211

@cboudereau
Copy link
Author

This version works perfectly with JDK 21 but the vscode extension "Language Support for Java(TM) by Red Hat" is complaining (it might be compatible with the JDK 20 even if it is a pre-release version v1.22.2023090904)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment