Hello,
for those who where not at the JVMLS, it may make sense to re-read this email 
later,
when the talk of Brian on Type class / witness is visible on youtube.
I write this now because i'm sure i will totally forget about that in few days.

During the talk, Brian said that witness are restricted to be used only by 
value classes so we avoid the operator overloading hell that you can see in 
other languages.

I think this restriction can be bypassed.

The problem is that you can always wrap any class into a value class organized 
as a monad (containing a superposition of states) thus bypassing that 
restriction.


As an example, let say we want to abuse of the >> operator to emulate C++ 
iostream.
Let suppose we have this witness interface defined in the JDK (it is by example 
used by Integer)

witness interface BitwiseNumeric<V> {
  V rightShift(V v1, V v2);

  // other methods
}

And the witness interface for exact conversion also defined in the JDK

witness interface Conversion<U, V> {
  U convert(V value);
}


So the trick is to create a value class that encode either a Writer or any 
value you want to add to the writer as a monad,
The exact conversion is used to wrap any value into the IOStream, the righShift 
is used to consume the wrapped value using a side-effect.

value class IOStream {
 private final Writer writer;
 private final Object o;

 private IOStream(Writer writer, Object o) { this.writer = writer; this.o = o; 
super(); }

 public IOWriter(Writer! writer) { this(writer, null); }  

 public static final witness BitwiseNumeric<IOStream!> BITWISE_NUMERIC = new 
BitwiseNumeric<>() {
   public IOStream! rightShift(IOStream! v1, IOStream! v2) {
     if (v1.writer == null || v2.writer != null) {
       throw new ISE();
     }
     v1.writer.append("" + v2.o);
     return v1;
   }

   // other methods throw UnsupportedOperationException
 };

 public static final witness Conversion<IOStream!, Integer!> FROM_INTEGER = new 
Conversion<>() {
   IOStream! convert(Integer! value) {
     return new IOStream(null, value);
   }
 };
}

So one can write
  IOStream stream = new IOStream(writer);
  var _ = stream >> 2 >> 3;

I think this is a general mechanism so any operator can be abused that way.

regards,
Rémi

Reply via email to