Skip to content

Add type constraints to classgenerics in methods #2868

@sampersand

Description

@sampersand

RBS currently only lets you add type constraints to generic variables when they're declared. (For class/modules, it looks like class Foo[P < _ToS] and for methods it looks like def print: [T < _ToS] (T) -> T).

I propose expanding the method form of this to support arbitrary constraints of class generics:

class CardboardBox[Contents]
  def add: (Contents) -> void
  def submerge!: {Contents < _Waterproof} () -> void
end

There's a lot of motivating examples of this in the stdlib. Here's a select few:

class Array[E]
  # `Array#join` requires the `E` to respond to `to_s`
  def join: {E < _ToS} (?string separator) -> String

  # `Array#sum` without a default argument requires `E`
  # to coerce with integers
  def sum: [R < _Add] {E < _Coerce[Integer, R]} () -> R
         | [I < _Add[E, O], O < _Add] (I default) -> O
end

module Enumerable[E] : _Each[E]
  # `Enumerable#include?` goes `element == object`,
  # which requires that `E` implements `==`, not `T`.
  def include?: [T] {E < _Equals[T]} (T object) -> bool
end

Few things to note:

  1. I'm not wed to the syntax—in fact, I'd probably prefer it if it were a part of the [] expression (eg def include?: [T, E < _Equals[T]]). But that might be difficult to implement, and the braces are currently unused before arguments
  2. This proposal only talks class generics, as that's a somewhat pressing need. However, it might be nice (and if it's easy to do), extend this syntax to support any form of constraints

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions