Skip to content
jckarter edited this page Apr 16, 2011 · 10 revisions

Motivation

Clay current allows protocols (or concepts or type classes, if you prefer) to be defined in an ad-hoc way, using CallDefined?:

   ForwardCoordinate?(T) = CallDefined?(dereference, T) and CallDefined?(inc, T);

While this works, it leaves the compiler with very little semantic information for error reporting or debugging—it can only report that the pattern match failed, not why. The CallDefined? syntax is also abstracted from actual expression syntax. First-class language support for protocols and function definition syntax for protocol-following types would allow for improvements in compiler error reporting and code readability, and would reduce boilerplate in common function definition cases.

Proposed implementation

There's plenty of prior art in designing the semantics of type constraints (ConceptC++, type classes in Haskell + the various GHC extensions, .NET generics, among others). The primary question in bringing them to Clay is syntax. We need a pattern matching form for constraining a pattern variable (such as "'X in Protocol") and forms for defining protocols (perhaps in both automatically-derived and formal forms), refinements of protocols, and formal instances of protocols.

A good spot-test is the sequence/iterator/coordinate family of protocols. Here's a theoretical definition of those protocols, using forall <pattern> in <ProtocolName>[<..ProtocolArgs>] { } as the syntactic form for protocol definitions, and <pattern> in <Protocol> as the pattern syntax for constrained pattern variables.

  forall 'I in IteratorType['E] {
      // required operations
      next(i: 'I) : 'E;
      hasNext?(i: 'I) : Bool;

      // derived definitions
      #IteratorTargetType('I) = 'E;
  }
  
  forall 'S in SequenceType['I in IteratorType] {
      // required operations
      iterator(x: 'S) : 'I;
      
      // derived definitions
      #SequenceIteratorType('S) = 'I;
      #SequenceElementType('S) = IteratorTargetType('I);
  }

  forall 'C in CoordinateType['E] {
      dereference(c: 'C) : 'E;
      inc(ref c: 'C) : ;
      dec(ref c: 'C) : ;
  
      #CoordinateTargetType('C) = 'E;
  }
  
  forall ('S in SequenceType['I]) in CoordinateSequenceType['I in IteratorType['E], 'C in CoordinateType['E]] {
      begin(s: 'S) : 'C;
      end(s: 'S) : 'C;

      #SequenceCoordinateType('S) = 'C;
  }

Discussion

Please add comments here.

Clone this wiki locally