Java – How do existential types differ from interfaces

interfacesjavatype-systems

Given the existential type

T = ∃X.{op₁:X, op₂:X→boolean}

and this generic Java interface:

interface T<X> {
    X op₁();
    boolean op₂(X something);
}

What are the fundamental differences between the existential type and the Java interface?

Obviously there are syntactical differences, and Java's object-orientation (which also includes details such as hidden this parameters etc.). I'm not so much interested in these as in conceptual and semantic differences — though if someone would like to shed light on some finer points (such as the notational difference between T vs. T<X>), that would be appreciated too.

Best Answer

Hmm... That definition looks very similar to some haskell sample I've seen long time ago.

{-# LANGUAGE ExistentialQuantification #-}
data X = forall a . X { value :: a, viewValue :: a -> String }
instance Show X where show (X { value = x, viewValue = f}) = f x
sample :: [X]
sample = [X 3 show, X "abc" show, X 3.14 show]

When constructor X is applied ∀ actually becomes ∃. Note that when you take out value you don't know the type and have empty set of operation over it. But since viewValue is kinda coherent with value it can be applied to it.

I guess the main difference of Java interface you proposed is the fact that you have to know intermediate type for passing result of op₁ to op₂. I.e. proper system for existential type should select the right type which is guaranteed to exist by condition. I.e. you should be able to write function with type: ∀X. X→(X→boolean)→T. In prev sample such function is X constructor used in X 3 show (show is function which takes argument of any type that implements Show and returns String)

Updated: I just re-read your question and I think I've got proper construction for Java:

interface T {
    boolean op₂();
}
...
T x = new T() {
    private final int op₁ = ...;
    public boolean op₂() { return ((op₁ % 2) == 0); }
};
T y = new T() {
    private final char op₁ = ...;
    public boolean op₂() { return ('0' <= op₁ && op₁ <= '9'); }
};
if (x.op₂() && y.op₂()) ...

You are right about mentioning this - it's actually your op₁.

So I guess I understood now that classical OOP languages (Java, C#, C++ etc) always implement existential type with single value this and a functions over it called "methods" which implicitly called with that value :)

P.S. Sorry, I'm not very familiar with Java, but I hope you've got the idea.

Related Topic