I was subsuming union types under sum types here, maybe a bit imprecisely.
The following already works in Java (and has for a long time):
interface F<X extends Exception, Y extends Exception>
{
void f(int n) throws X, Y;
}
void g() throws IOException, SQLException
{
F<IOException, SQLException> f = n ->
{
if (n > 0) throw new IOException();
else throw new SQLException();
};
h(f, 0);
}
<X extends Exception, Y extends Exception>
void h(F<X, Y> f, int n) throws X, Y
{
f.f(n);
}
We merely want for
F and
h to be able to work for any number of exception types. We don't need the ability to declare variables of type
X |
Y for that.
Of course, it would be nice not having to write IOException, SQLException multiple times in g, and instead have some shortcut for it, but that's not strictly necessary.
The main problem currently is that you have to define F1, F2, F3,... as well as h1, h2, h3,... to cover different numbers of exception types, instead of having just a single definition that would abstract over the number of exception types.