Re: Question about pattern matching and sealed types – redundant switch cases
Brian Goetz
brian.goetz at oracle.com
Sat Apr 19 17:34:14 UTC 2025
Right, you've built a monad here, and you want to express the happy path
with a monadic do. In Haskell you'd write this as:
do
something <- getSomething()
result <- doThingWithSomething(something)
and let the language desugar it accordingly. But you can do this
yourself in Java!
sealed interface Result<T> permits Ok, Err {
<U> Result<U> andThen(ThrowyFunction<T, U> f);
static<T> Result<T> of(ThrowySupplier<T> s) { ... }
}
and then express your code as:
Result.of(() -> getSomething())
.andThen(C::doThingWithSomething)
...
No nested code needed.
On 4/19/2025 1:26 PM, Andreas Berheim Brudin wrote:
> Thank you both for the quick replies.
>
> I guess the fact that b1 and b2 is available outside of the if, hints
> at some kind of flow-based type analysis (even though the new type is
> implicitly declared in the pattern), but I would then have proven
> Brian's point - that once that door is open, people will ask for more.
>
> But given the semantics of Java, I understand that this doesn't fit
> very well. The reason I ask was that we use a Result type (Ok/Err)
> quite a lot, and the biggest complaint is the nestedness of the code,
> which often becomes:
> return switch(getSomething()) {
> case Err(var e) -> yield someError(e);
> case Ok(var something) -> {
> yield switch (doThingWithSomething(something)) {
> case Err(var e) -> yield someOtherError(e);
> case Ok(var result) -> etc...
> }
> }
>
> I guess you don't have any quick fixes for that other than resorting
> to traditional exception handling.
>
> Best,
> Andreas
>
> On Sat, Apr 19, 2025 at 7:08 PM Remi Forax <forax at univ-mlv.fr> wrote:
>
>
>
> ------------------------------------------------------------------------
>
> *From: *"Andreas Berheim Brudin" <andreas.brudin at gmail.com>
> *To: *"amber-dev" <amber-dev at openjdk.org>
> *Sent: *Saturday, April 19, 2025 6:17:43 PM
> *Subject: *Question about pattern matching and sealed types –
> redundant switch cases
>
> Hi all,
>
> I'm new to the list—apologies if this has been discussed
> before, and thanks in advance for your time.
>
> I have a question about pattern matching with sealed types.
> Consider this example:
>
> sealed interface A permits B, C {}
> record B(String b1, String b2) implements A {}
> record C(String c) implements A {}
>
> A myVar = ...;
> if (!(myVar instanceof B(var b1, var b2))) {
> return switch (myVar) {
> case C(var c) -> c;
> case B b -> throw new IllegalStateException("should
> not happen");
> };
> }
> // use b1, b2
>
> Here, I want to keep an early-return style, but since I need
> to return a value from C, I have to use a switch. This leads
> to redundancy: we've already tested myVar is not a B, so that
> case should be statically unreachable.
>
> My questions:
>
> 1. Is there any consideration or ongoing work to allow the
> compiler to automatically eliminate such unreachable cases?
>
>
> The short answer is no :)
>
> Long answer,
> (1) myVar does not change its type, it is declared as an A, it
> always be an A (Groovy or Kotlin behave differently, they use flow
> typing)
> (2) the type system of Java has no notion of exclusion, the type
> A but not B does not exist
> (3) instanceof and switch does not have the same semantics,
> instanceof has no notion of exhaustiveness while a switch on a
> sealed type has.
>
> so because of (1) the type of myVar can not be changed, because of
> (2) its new type inside the if can not be "A but not B" and
> because of (3) the new type can not be only C.
>
>
>
> 2. If only one case remains (in this case, C), could it be
> possible to treat the variable as a C directly without
> requiring an explicit switch?
>
>
> No,
>
>
>
> Again, apologies if this has already been discussed. I'd
> appreciate any pointers to relevant threads or JEPs if so.
>
>
> The relevant JEPs are JEP 394 (for instanceof) and 441 (for switch).
>
>
>
> Thanks,
> Andreas
>
>
> regards,
> Rémi
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20250419/488093e9/attachment-0001.htm>
More information about the amber-dev
mailing list