dart-lang / language

Design of the Dart language
Other
2.65k stars 201 forks source link

Allow recursive extension type #3930

Open mmcdon20 opened 2 months ago

mmcdon20 commented 2 months ago

This is kind of an alternative to allow recursive typedef.


This would allow for recursive data structures backed by records such as in the following examples:

extension type const LinkedList<T>._((T head, LinkedList<T>? tail) _impl) {
  const LinkedList(T head, [LinkedList<T>? tail]) : _impl = (head, tail);
  T get head => _impl.$1;
  LinkedList<T>? get tail => _impl.$2;
}

extension type const BinaryTree<T>._(
    ({BinaryTree<T>? left, BinaryTree<T>? right, T value}) _impl) {
  const BinaryTree(
      {required T value, BinaryTree<T>? left, BinaryTree<T>? right})
      : _impl = (left: left, right: right, value: value);

  T get value => _impl.value;
  BinaryTree<T>? get left => _impl.left;
  BinaryTree<T>? get right => _impl.right;
}

const LinkedList<int> list = LinkedList(1, LinkedList(2, LinkedList(3)));
const BinaryTree<String> tree = BinaryTree(
    value: 'A', left: BinaryTree(value: 'B'), right: BinaryTree(value: 'C'));

This would also allow for recursive Function definitions, such as in the following example:

extension type Church(Church Function(Church) _impl) {
  Church call(Church f) => _impl(f);
}

final Church church = Church((f) => f);

If union types are also added, then you could potentially represent a Json type this way:

extension type Json(Map<String, Json> | List<Json> | String | num | bool | Null _)
    implements Map<String, Json> | List<Json> | String | num | bool | Null {}

The above definitions could potentially be improved further if allow extension type to implement Record and Function types, and/or implicit coercion through implicit constructors are also added to the language.

lrhn commented 2 months ago

It's not allowed because it's impossible to represent the extension-type erased representation type in the current Dart type system. Dart would have to add recursive types to the type system before this would be possible.

So this is not an alternative to recursive type aliases, it's basically the same feature, and if we have recursive types in the type system anyway, we might as well allow them in general using recursive type aliases.