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