Hi.
Okay so Java. I think things are like less rotten and also less state than I would maybe think. Or at least they can be.
Sealed interfaces implemented by records make fine sum types:
public sealed interface BI {
record B(boolean b) implements BI {}
record I(int i) implements BI {}
}
If we want to define the summands in a different place we might need to use permits
:
public sealed interface BI permits B, I {}
// define I and B elsewhere
We can make a BI
value from a boolean
or from an int
:
public final static java.util.Random random = new java.util.Random();
public static BI.B b() {
return new BI.B(random.nextInt(2) > 0);
}
public static BI.I i() {
return new BI.I(random.nextInt());
}
public static BI bi() {
return random.nextInt(2) > 0 ? b() : i();
}
And records make fine products:
public record Pair(BI a, BI b) {}
Let's pattern match with switch
:)
In a couple of different ways: One switch
will check all the possible BI.B
/BI.I
combinations. The other switch
will have some cases that are more "if it's a BI.
and whatever, then such and such." Both are exhaustive without using default
cases, and Java will tell us if circumstances change in ways that make it so all cases are not covered (e.g. if we add a third implementation of BI
).
public static void test() {
var p = new Pair(bi(), bi());
System.out.print(p);
System.out.print(switch(p) {
case Pair(BI.B(var a), BI.B(var b)) -> " %s ".formatted(a || b);
case Pair(BI.B(var _), BI.I(var _)) -> " bi ";
case Pair(BI.I(var _), BI.B(var _)) -> " ib ";
case Pair(BI.I(var a), BI.I(var b)) -> " %s ".formatted(a + b);
});
System.out.println(switch(p) {
case Pair(BI.B(var _), var _), Pair(var _, BI.B(var _)) -> "b";
case Pair(BI.I(var _), BI.I(var _)) -> "i";
});
}
Can run it with some values:
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
test();
}
}
One test run gave this:
Pair[a=B[b=true], b=B[b=false]] true b
Pair[a=I[i=1446473161], b=B[b=true]] ib b
Pair[a=B[b=false], b=B[b=false]] false b
Pair[a=B[b=false], b=I[i=-1934537206]] bi b
Pair[a=I[i=1251217138], b=I[i=-12664252]] 1238552886 i
Pair[a=B[b=false], b=B[b=false]] false b
Pair[a=I[i=2071893759], b=I[i=1527894353]] -695179184 i
Pair[a=I[i=-259687046], b=I[i=-2067391554]] 1967888696 i
Pair[a=I[i=-78306323], b=I[i=1503432803]] 1425126480 i
Pair[a=I[i=-1525890285], b=B[b=true]] ib b
Okay.
As of Java 21 to 24 or so, there's some stuff you could expect to have that isn't there. Mostly what kinds of types can be used for the pattern matching stuff and what can and can't be nested. I think most of that stuff is on the roadmap and is being worked on. Anyway there are some annoyances to run into I guess, but IMO nothing too major.