Skip to content

Allow classes to be parametric in other parametric classes #1213

Open
@metaweta

Description

@metaweta

This is a proposal for allowing generics as type parameters. It's currently possible to write specific examples of monads, but in order to write the interface that all monads satisfy, I propose writing

interface Monad<T<~>> {
  map<A, B>(f: (a: A) => B): T<A> => T<B>;
  lift<A>(a: A): T<A>;
  join<A>(tta: T<T<A>>): T<A>;
}

Similarly, it's possible to write specific examples of cartesian functors, but in order to write the interface that all cartesian functors satisfy, I propose writing

interface Cartesian<T<~>> {
  all<A>(a: Array<T<A>>): T<Array<A>>;
}

Parametric type parameters can take any number of arguments:

interface Foo<T<~,~>> {
  bar<A, B>(f: (a: A) => B): T<A, B>;
}

That is, when a type parameter is followed by a tilde and a natural arity, the type parameter should be allowed to be used as a generic type with the given arity in the rest of the declaration.

Just as is the case now, when implementing such an interface, the generic type parameters should be filled in:

class ArrayMonad<A> implements Monad<Array> {
  map<A, B>(f: (a:A) => B): Array<A> => Array<B> {
    return (arr: Array<A>) =>  arr.map(f);
  }
  lift<A>(a: A): Array<A> { return [a]; }
  join<A>(tta: Array<Array<A>>): Array<A> {
    return tta.reduce((prev, cur) => prev.concat(cur));
  }
}

In addition to directly allowing compositions of generic types in the arguments, I propose that typedefs also support defining generics in this way (see issue 308):

typedef Maybe<Array<~>> Composite<~> ;
class Foo implements Monad<Composite<~>> { ... }

The arities of the definition and the alias must match for the typedef to be valid.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions