Generics Plans

Alexis King edited this page Mar 18, 2015 · 4 revisions

Planned features for Racket's generic functions library (racket/generic).

  • Implement inheritance of partial method tables (see http://lists.racket-lang.org/users/archive/2013-March/056791.html)
  • Polish the design of a gen:buildable-sequence interface (possible starting point: https://github.com/stamourv/buildable-sequences)
    • would be great if this came with a set of operations like map/s, foldl/s, take/s, etc. that just lets us not care about the type of sequence we're using.
  • Speed up dispatch by using macro-introduced inline caches (tonyg has a starting point somewhere)
  • Come up with a good multiple dispatch story that avoids mutation issues
  • Integration with interfaces from Racket's object system
  • Add first-class documentation support to scribble/manual via defgenerics, likely similar to defclass/definterface

Proposed extensions to the generics system

I (Alexis) have recently worked on implementing a generic collections library. In doing so, I've found a few things I think need to be added to racket/generic to make everything operate smoothly.

Implementation requirements

This is easy. Generic interfaces should be able to specify that implementations need to satisfy arbitrary contracts. This is most helpful when a certain interface is designed to be an extension of another. For example, to use an example from Haskell, given gen:monad, the following declaration should be possible:

(define-generics monad-plus
  #:implementation-contract monad?
  ...)

This doesn't need to be a part of the internal plumbing of generics, since it can just be applied as a contract to the individual methods.

Interface instances for interfaces

This is a little more complicated, but this is probably what I'd find the most important to having a complete generics system. Take the following generic definitions:

(define-generics iterator
  (iterator-empty? iterator)
  (iterator-next iterator)
  (iterator-ref iterator))

(define-generics iterable
  ; iterable? -> iterator?
  (get-iterator iterable))

Now it needs to be possible to do something like this:

(struct cons-iterator (sequence)
  #:methods gen:iterator
  [(define (iterator-empty? v)
     (empty? (cons-iterator-sequence v)))
   (define (iterator-next v)
     (cons-iterator (rest (cons-iterator-sequence v))))
   (define (iterator-ref v)
     (first (cons-iterator-sequence v)))])

(define-generics cons-sequence
  (empty? cons-sequence)
  (first cons-sequence)
  (rest cons-sequence)
  #:methods gen:iterable
  [(define (get-iterator v) (cons-iterator v))])

I think having functionality like this is essential for providing an expressive generics system. The idea is that if you implement a certain interface, you can get an implementation of another interface "for free".

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.