Description
With sealed
class families and pattern matching developers are understandably excited to use them for data modelling in their programs. However the syntax is overly verbose for simple families, e.g. modelling success / failure in the API requires writing something like this:
sealed class Result<T> {
const Result();
}
class Ok<T> extends Result<T> {
final T value;
const Ok<T>(this.value);
}
class Error extends Result<Never> {
final String message;
const Error(this.message);
}
With primary constructors this is reduced to
sealed class Result<T> {
const Result();
}
class Ok<T>(final T value) extends Result<T>;
class Error(final String message) extends Result<Never>;
Which is much better but still has some repeated boilerplate here: repeated extends Result<*>
.
I suggest expanding upon primary constructors and introduce a special syntactic sugar for simple sealed families like this
sealed class Result<T> {
case Ok<T>(final T value);
case Error(final String message);
}
Here case C<T1, ..., Tn>(v0, ..., vN) { m1 ... mN }?
occurring inside sealed class B<U1, ..., Un>
gives raise to
class C<T1, ..., Tn>(v0, ..., vN) extends B<Forward({Ti}, {Ui})> {
// Optional methods
m1
// ...
mN
}
Forward(...)
is defined as forwarding type parameters based on their names (or maybe indices - I am not sure what is better). If Ui
does not have a corresponding Ti
then Never
is passed instead.
/cc @munificent @lrhn