interface Upper<T extends <Upper<T>>
def consume(upper: Upper[T] forSome {type T <: Upper[T]})
public class TestRecursiveTypes{// Base interface for F-Bounded polymorphismpublic interface Upper<T extends Upper<T>>{public T map();}// Implementation of F-Bounded polymorphismpublic static class UpperImpl implements Upper<UpperImpl>{@Overridepublic UpperImpl map(){System.out.println(String.format("map@%s",this));return new UpperImpl();}}// Consumer interfacepublic interface UpperConsumer{void consume(Upper<?> upper_);}// Consumer implementationpublic static class Consumer implements UpperConsumer{@Overridepublic void consume(Upper<?> upper_){upper_.map().map().map();}}// Upper factory method, returns interfacepublic Upper<?> provideUpper(){return new UpperImpl();}public static void main(String[] args){new TestRecursiveTypes().run();}private void run(){Upper<?> upper = new UpperImpl();// This is also an upper, without conversioUpper<?> mapped = upper.map();Upper<?> upper2 = provideUpper();new Consumer().consume(upper2.map().map().map());}}
import TestRecursiveTypes._import language.existentialsobject TestRecursiveTypesScala {def main(args: Array[String]): Unit = {val impl = new UpperImpl()impl.map().map().map()val upper = new TestRecursiveTypes().provideUpper()upper.map().map().map()}class Consumer extends UpperConsumer {def consume(upper: Upper[_]): Unit = {upper.map().map()}}}
void consume(Upper<?> upper_);
override def consume(upper: Upper[_]) ={...}
Still not implementing the Java interface…
Still not implementing the Java interface…
On Monday, 12 January 2015 22:51:38 UTC+1, Juha Heljoranta wrote:trait Upper[T <: Upper[T]] {
def map(): T
}
class UpperImpl extends Upper[UpperImpl] {
def map: UpperImpl = new UpperImpl
}
class Consumer {
def consume(upper: T forSome { type T <: Upper[T] }) =
upper.map.map.map
}
class Test {
def provideUpper() = new UpperImpl()
val upper = new UpperImpl()
val mapped = upper.map()
val upper2 = provideUpper()
new Consumer().consume(upper2.map().map().map())
}
Cheers,
Juha
class Consumer extends UpperConsumer {
def consume(upper: Upper[_]): Unit
= {
fbound(upper).map().map()
}
}
// Workaround for the limbo state given that:
// a) Java wildcard types propagate bounds (after the fix for https://issues.scala-lang.org/browse/SI-6169)
// b) Scala existentials don't https://issues.scala-lang.org/browse/SI-1786
def fbound(u: Upper[_]) = u.asInstanceOf[Upper[A] forSome { type A <: Upper[A] }]
Thanks, Jason - no elegant solution for now then, but hope for the future.Purely as a matter of interest, do you have any insight on the inconsistency I mentioned earlier: the compiler correctly infers a return type (from a Java API) of Upper<?> to be Upper[A] forSome { type A <: Upper[A] }, but when implementing a method from a Java interface with an argument of the same type only Upper[_] is accepted?