14

I've been working with C# for a while and trying to get more familiar with Java. So I'm trying to migrate some of the basic patterns I use on daily basis in C# even only to understand the gap between JVM and dotnet and figure out how to deal with them. Here is the first problem I encountered - an option type - somethiong which is quite easy to achieve in many languages i.e. Koltlin:

sealed class Option<out T : Any> {
    object None : Option<Nothing>()
    data class Some<out T : Any>(val value: T) : Option<T>()}

so I can easily create a map functor:

fun <T : Any, B : Any> Option<T>.map(f: (T) -> B): Option<B> =
    when (this) {
        is Option.None -> Option.None
        is Option.Some -> Option.Some(f(this.value))} 

Is this something I can achieve in Java? Im not concerned about the lack of extentions methods, I can leave without that, but how to perform the actual type matching without having to rely on an unchecked cast? At least thats what IntelliJ is complaining about...

Michal Pawluk
  • 401
  • 1
  • 4
  • 10
  • 1
    You are asking about Java, but show no Java code. I feel this isn't right. – M. Prokhorov Mar 26 '18 at 12:44
  • 1
    Neither C# nor Java have union types, and any workarounds will be awkward to use at best. For a .NET language that does have union types, please look at F#. – dumetrulo Mar 26 '18 at 13:00
  • 1
    Looks perhaps like you are looking for [java.util.Optional](https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html) from Java 8. – OldCurmudgeon Mar 26 '18 at 13:06
  • 1
    There isn't anything exactly equivalent - but why do you need a Java solution, when you already have one in Kotlin, which has perfectly working interop? – Moira Mar 26 '18 at 13:15
  • @dumetrulo, you can easily simulate union types in C# without much typing, not as cleanly as in F# but perfectly usable, you can also do pattern-match generic types which is rather difficult in Java due to generic types erasure. The question how to achieve the same in Java. – Michal Pawluk Mar 26 '18 at 13:16
  • @Moira, you are right, unfortunately Java is the only approved JVM technology at my worklplace. – Michal Pawluk Mar 26 '18 at 13:24
  • 1
    @OldCurmudgeon, I seems like the java.util.Optional should do the job in case of the Option/Maybe type. Thanks for the suggestion. – Michal Pawluk Mar 26 '18 at 13:56
  • Thanks All, I guess I'll need to start my Java learning excersise with something more down-to-the-earth. – Michal Pawluk Mar 26 '18 at 13:58

1 Answers1

11

in the specific case you mentioned, the following would work:

Java doesn't have pattern matching. The closest you can get to pattern matching in Java is with the visitor pattern.

usage:

UnionType unionType = new TypeA();

Integer count = unionType.when(new UnionType.Cases<Integer>() {
    @Override
    public Integer is(TypeA typeA) {
        // TypeA-specific handling code
    }

    @Override
    public Integer is(TypeB typeB) {
        // TypeB-specific handling code
    }
});

boilerplate code:

interface UnionType {
    <R> R when(Cases<R> c);

    interface Cases<R> {
        R is(TypeA typeA);

        R is(TypeB typeB);
    }
}

class TypeA implements UnionType {

    // ... TypeA-specific code ...

    @Override
    public <R> R when(Cases<R> cases) {
        return cases.is(this);
    }
}

class TypeB implements UnionType {

    // ... TypeB-specific code ...

    @Override
    public <R> R when(Cases<R> cases) {
        return cases.is(this);
    }
}
Eric
  • 12,320
  • 4
  • 53
  • 63