diff options
Diffstat (limited to 'tests/disabled')
-rw-r--r-- | tests/disabled/neg/named-params.scala | 37 | ||||
-rw-r--r-- | tests/disabled/pos/CollectionStrawMan3.scala | 408 | ||||
-rw-r--r-- | tests/disabled/pos/flowops.scala | 31 | ||||
-rw-r--r-- | tests/disabled/pos/flowops1.scala | 39 | ||||
-rw-r--r-- | tests/disabled/pos/hk-named.scala | 58 | ||||
-rw-r--r-- | tests/disabled/pos/named-params.scala | 90 |
6 files changed, 663 insertions, 0 deletions
diff --git a/tests/disabled/neg/named-params.scala b/tests/disabled/neg/named-params.scala new file mode 100644 index 000000000..5a2375b15 --- /dev/null +++ b/tests/disabled/neg/named-params.scala @@ -0,0 +1,37 @@ +package namedparams + +class C[type Elem, type Value](val elem: Elem) { + def toVal: Elem = ??? +} + +abstract class D[type Elem, V](elem: Elem) extends C[Elem, V](elem) +abstract class D2[Elem, V](elem: Elem) extends C[Elem, V](elem) // error +abstract class D3[type Elem, V](x: V) extends C[V, V](x) // error +abstract class D4[type Elem](elem: Elem) extends C[Elem, Elem] // error +object Test { + val c = new C[String, String]("A") { + override def toVal = elem + } + val x: c.Elem = c.elem + + val c2: C { type Elem = String } = c + + val c3 = new C[Elem = String, Value = Int]("B") + val c4 = new C[Elem = String]("C") + val x2: c2.Elem = c2.elem + + val c5 = new C[Elem1 = String, Value0 = Int]("B") // error // error + + def d2[E, V](x: E) = new C[Elem = E, Value = V](x) + + val dup = d2[E = Int, V = String, E = Boolean](2) // error + val z1 = d2[Elem = Int, Value = String](1) // error // error + val z2 = d2[Value = String, Elem = Int](1) // error // error + val z3 = d2[Elem = Int](1) // error + val z4 = d2[Value = Int]("AAA") // error + val z5 = d2[Elem = Int][Value = String](1) //error // error + +} + + + diff --git a/tests/disabled/pos/CollectionStrawMan3.scala b/tests/disabled/pos/CollectionStrawMan3.scala new file mode 100644 index 000000000..c21a73f00 --- /dev/null +++ b/tests/disabled/pos/CollectionStrawMan3.scala @@ -0,0 +1,408 @@ +package strawman.collections + +import Predef.{augmentString => _, wrapString => _, _} +import scala.reflect.ClassTag + +/** A strawman architecture for new collections. It contains some + * example collection classes and methods with the intent to expose + * some key issues. It would be good to compare this to other + * implementations of the same functionality, to get an idea of the + * strengths and weaknesses of different collection architectures. + * + * For a test file, see tests/run/CollectionTests.scala. + * + * This one is like CollectionStrawMan1, but with the named parameter + * scheme for hk types. + */ +object CollectionStrawMan1 { + + /* ------------ Base Traits -------------------------------- */ + + /** Replaces TraversableOnce */ + trait CanIterate[type +Elem] { + def iterator: Iterator[Elem] + } + + /** Base trait for instances that can construct a collection from an iterator */ + trait FromIterator[+C <: Iterable] { + def fromIterator[B](it: Iterator[B]): C[Elem = B] + } + + /** Base trait for companion objects of collections */ + trait IterableFactory[+C <: Iterable] extends FromIterator[C] { + def empty[X]: C[Elem = X] = fromIterator(Iterator.empty) + def apply[A](xs: A*): C[Elem = A] = fromIterator(Iterator(xs: _*)) + } + + /** Base trait for generic collections */ + trait Iterable[type +Elem] extends CanIterate[Elem] with FromIterator[Iterable] + + /** Base trait for sequence collections */ + trait Seq[type +Elem] extends Iterable[Elem] with FromIterator[Seq] { + def apply(i: Int): Elem + def length: Int + } + + /* ------------ Operations ----------------------------------- */ + + /** Operations returning types unrelated to current collection */ + trait Ops[A] extends Any { + def iterator: Iterator[A] + def foreach(f: A => Unit): Unit = iterator.foreach(f) + def foldLeft[B](z: B)(op: (B, A) => B): B = iterator.foldLeft(z)(op) + def foldRight[B](z: B)(op: (A, B) => B): B = iterator.foldRight(z)(op) + def indexWhere(p: A => Boolean): Int = iterator.indexWhere(p) + def isEmpty: Boolean = !iterator.hasNext + def head: A = iterator.next + def view: View[A] = new View(iterator) + def to[C <: Iterable](fi: FromIterator[C]): C[Elem = A] = fi.fromIterator(iterator) + } + + /** Transforms returning same collection type */ + trait MonoTransforms[A, Repr] extends Any { + protected def iter: Iterator[A] + protected def fromIter(it: => Iterator[A]): Repr + def partition(p: A => Boolean): (Repr, Repr) = { + val (xs, ys) = iter.partition(p) + (fromIter(xs), fromIter(ys)) + } + def drop(n: Int): Repr = fromIter(iter.drop(n)) + } + + /** Transforms returning same collection type constructor */ + trait PolyTransforms[A, C <: CanIterate] extends Any { + protected def iter: Iterator[A] + protected def fromIter[B](it: => Iterator[B]): C[Elem = B] + def map[B](f: A => B): C[Elem = B] = fromIter(iter.map(f)) + def flatMap[B](f: A => CanIterate[B]): C[Elem = B] = fromIter(iter.flatMap(f(_))) + def ++[B >: A](xs: CanIterate[B]): C[Elem = B] = fromIter(iter ++ xs) + def zip[B](xs: CanIterate[B]): C[Elem = (A, B)] = fromIter(iter.zip(xs.iterator)) + } + + /** Transforms that only apply to Seq */ + trait MonoTransformsOfSeqs[A, Repr] extends Any with MonoTransforms[A, Repr] { + def reverse: Repr = fromIter(iter.reverse) + } + + /** Implementation of Ops for all generic collections */ + implicit class IterableOps[A](val c: Iterable[A]) + extends AnyVal with Ops[A] { + def iterator = c.iterator + } + + /** Implementation of MonoTransforms for all generic collections */ + implicit class IterableMonoTransforms[A, C <: Iterable](val c: Iterable[A] with FromIterator[C]) + extends AnyVal with MonoTransforms[A, C[Elem = A]] { + protected def iter = c.iterator + protected def fromIter(it: => Iterator[A]): C[Elem = A] = c.fromIterator(it) + } + + /** Implementation of PolyTransforms for all generic collections */ + implicit class IterablePolyTransforms[A, C <: Iterable](val c: Iterable[A] with FromIterator[C]) + extends AnyVal with PolyTransforms[A, C] { + protected def iter = c.iterator + protected def fromIter[B](it: => Iterator[B]) = c.fromIterator(it) + } + + /** Implementation of MonoTransformsForSeqs for all generic collections */ + implicit class SeqMonoTransforms[A, C <: Seq](val c: Seq[A] with FromIterator[C]) + extends AnyVal with MonoTransformsOfSeqs[A, C[Elem = A]] { + protected def iter = c.iterator + protected def fromIter(it: => Iterator[A]) = c.fromIterator(it) + } + + /* --------- Concrete collection types ------------------------------- */ + + /** Concrete collection type: List */ + sealed trait List[type +Elem] extends Seq[Elem] with FromIterator[List] { + def isEmpty: Boolean + def head: Elem + def tail: List[Elem] + def iterator = new ListIterator[Elem](this) + def fromIterator[B](it: Iterator[B]): List[B] = List.fromIterator(it) + def apply(i: Int): Elem = { + require(!isEmpty) + if (i == 0) head else tail.apply(i - 1) + } + def length: Int = + if (isEmpty) 0 else 1 + tail.length + } + + case class Cons[+A](x: A, xs: List[A]) extends List[A] { + def isEmpty = false + def head = x + def tail = xs + } + + case object Nil extends List[Nothing] { + def isEmpty = true + def head = ??? + def tail = ??? + } + + object List extends IterableFactory[List] { + def fromIterator[B](it: Iterator[B]): List[B] = it match { + case it: ListIterator[B] => it.toList + case _ => if (it.hasNext) Cons(it.next, fromIterator(it)) else Nil + } + } + + class ListIterator[+A](xs: List[A]) extends Iterator[A] { + private[this] var current = xs + def hasNext = !current.isEmpty + def next = { val r = current.head; current = current.tail; r } + def toList = current + } + + /** Concrete collection type: ArrayBuffer */ + class ArrayBuffer[type Elem] private (initElems: Array[AnyRef], initLength: Int) extends Seq[Elem] with FromIterator[ArrayBuffer] { + def this() = this(new Array[AnyRef](16), 0) + private var elems: Array[AnyRef] = initElems + private var start = 0 + private var limit = initLength + def apply(i: Int) = elems(start + i).asInstanceOf[Elem] + def length = limit - start + def iterator = new ArrayBufferIterator[Elem](elems, start, length) + def fromIterator[B](it: Iterator[B]): ArrayBuffer[B] = + ArrayBuffer.fromIterator(it) + def +=(elem: Elem): this.type = { + if (limit == elems.length) { + if (start > 0) { + Array.copy(elems, start, elems, 0, length) + limit -= start + start = 0 + } + else { + val newelems = new Array[AnyRef](limit * 2) + Array.copy(elems, 0, newelems, 0, limit) + elems = newelems + } + } + elems(limit) = elem.asInstanceOf[AnyRef] + limit += 1 + this + } + def trimStart(n: Int): Unit = start += (n max 0) + override def toString = s"ArrayBuffer(${elems.slice(start, limit).mkString(", ")})" + } + + object ArrayBuffer extends IterableFactory[ArrayBuffer] { + def fromIterator[B](it: Iterator[B]): ArrayBuffer[B] = it match { + case Iterator.Concat(fst: ArrayBufferIterator[_], snd: ArrayBufferIterator[_]) => + val elems = new Array[AnyRef](fst.remaining + snd.remaining) + Array.copy(fst.elems, fst.start, elems, 0, fst.remaining) + Array.copy(snd.elems, snd.start, elems, fst.remaining, snd.remaining) + new ArrayBuffer(elems, elems.length) + case it @ Iterator.Partition(underlying, _, buf, _) => + while (underlying.hasNext) it.distribute() + buf.asInstanceOf[ArrayBuffer[B]] + case it if it.remaining >= 0 => + val elems = new Array[AnyRef](it.remaining) + for (i <- 0 until elems.length) elems(i) = it.next.asInstanceOf[AnyRef] + new ArrayBuffer[B](elems, elems.length) + case _ => + val buf = new ArrayBuffer[B] + while (it.hasNext) buf += it.next + buf + } + } + + class ArrayBufferIterator[A](val elems: Array[AnyRef], initStart: Int, length: Int) extends RandomAccessIterator[A] { + val limit = length + def apply(n: Int) = elems(initStart + n).asInstanceOf[A] + } + + /** Concrete collection type: View */ + class View[type +Elem](it: => Iterator[Elem]) extends CanIterate[Elem] { + def iterator = it + } + + implicit class ViewOps[A](val v: View[A]) extends AnyVal with Ops[A] { + def iterator = v.iterator + def cache = to(ArrayBuffer).view + } + + implicit class ViewMonoTransforms[A](val v: View[A]) + extends AnyVal with MonoTransforms[A, View[A]] { + protected def iter = v.iterator + protected def fromIter(it: => Iterator[A]): View[A] = new View(it) + } + + implicit class ViewPolyTransforms[A](val v: View[A]) + extends AnyVal with PolyTransforms[A, View] { + protected def iter = v.iterator + protected def fromIter[B](it: => Iterator[B]) = new View(it) + } + + /** Concrete collection type: String */ + implicit class StringOps(val s: String) extends AnyVal with Ops[Char] { + def iterator: Iterator[Char] = new RandomAccessIterator[Char] { + override val limit = s.length + def apply(n: Int) = s.charAt(n) + } + } + + implicit class StringMonoTransforms(val s: String) + extends AnyVal with MonoTransformsOfSeqs[Char, String] { + protected def iter = StringOps(s).iterator + protected def fromIter(it: => Iterator[Char]) = { + val sb = new StringBuilder + for (ch <- it) sb.append(ch) + sb.toString + } + } + + implicit class StringPolyTransforms(val s: String) + extends AnyVal with PolyTransforms[Char, Seq] { + protected def iter = StringOps(s).iterator + protected def fromIter[B](it: => Iterator[B]) = List.fromIterator(it) + def map(f: Char => Char): String = { + val sb = new StringBuilder + for (ch <- s) sb.append(f(ch)) + sb.toString + } + def flatMap(f: Char => String) = { + val sb = new StringBuilder + for (ch <- s) sb.append(f(ch)) + sb.toString + } + def ++(xs: CanIterate[Char]): String = { + val sb = new StringBuilder(s) + for (ch <- xs.iterator) sb.append(ch) + sb.toString + } + def ++(xs: String): String = s + xs + } + +/* ---------- Iterators --------------------------------------------------- */ + + /** A core Iterator class */ + trait Iterator[+A] extends CanIterate[A] { self => + def hasNext: Boolean + def next: A + def iterator = this + def foldLeft[B](z: B)(op: (B, A) => B): B = + if (hasNext) foldLeft(op(z, next))(op) else z + def foldRight[B](z: B)(op: (A, B) => B): B = + if (hasNext) op(next, foldRight(z)(op)) else z + def foreach(f: A => Unit): Unit = + while (hasNext) f(next) + def indexWhere(p: A => Boolean): Int = { + var i = 0 + while (hasNext) { + if (p(next)) return i + i += 1 + } + -1 + } + def map[B](f: A => B): Iterator[B] = Iterator.Map(this, f) + def flatMap[B](f: A => CanIterate[B]): Iterator[B] = Iterator.FlatMap(this, f) + def ++[B >: A](xs: CanIterate[B]): Iterator[B] = Iterator.Concat(this, xs.iterator) + def partition(p: A => Boolean): (Iterator[A], Iterator[A]) = { + val lookaheadTrue, lookaheadFalse = new ArrayBuffer[A] + (Iterator.Partition(this, p, lookaheadTrue, lookaheadFalse), + Iterator.Partition[A](this, !p(_), lookaheadFalse, lookaheadTrue)) + } + def drop(n: Int): Iterator[A] = Iterator.Drop(this, n) + def zip[B](that: CanIterate[B]): Iterator[(A, B)] = Iterator.Zip(this, that.iterator) + def reverse: Iterator[A] = { + var elems: List[A] = Nil + while (hasNext) elems = Cons(next, elems) + elems.iterator + } + + /** If this iterator results from applying a transfomation to another iterator, + * that other iterator, otherwise the iterator itself. + */ + def underlying: Iterator[_] = this + + /** If the number of elements still to be returned by this iterator is known, + * that number, otherwise -1. + */ + def remaining = -1 + } + + object Iterator { + val empty: Iterator[Nothing] = new Iterator[Nothing] { + def hasNext = false + def next = ??? + override def remaining = 0 + } + def apply[A](xs: A*): Iterator[A] = new RandomAccessIterator[A] { + override val limit = xs.length + def apply(n: Int) = xs(n) + } + def nextOnEmpty = throw new NoSuchElementException("next on empty iterator") + + case class Map[A, B](override val underlying: Iterator[A], f: A => B) extends Iterator[B] { + def hasNext = underlying.hasNext + def next = f(underlying.next) + override def remaining = underlying.remaining + } + case class FlatMap[A, B](override val underlying: Iterator[A], f: A => CanIterate[B]) extends Iterator[B] { + private var myCurrent: Iterator[B] = Iterator.empty + private def current = { + while (!myCurrent.hasNext && underlying.hasNext) + myCurrent = f(underlying.next).iterator + myCurrent + } + def hasNext = current.hasNext + def next = current.next + } + case class Concat[A](override val underlying: Iterator[A], other: Iterator[A]) extends Iterator[A] { + private var myCurrent = underlying + private def current = { + if (!myCurrent.hasNext && myCurrent.eq(underlying)) myCurrent = other + myCurrent + } + def hasNext = current.hasNext + def next = current.next + override def remaining = + if (underlying.remaining >= 0 && other.remaining >= 0) + underlying.remaining + other.remaining + else -1 + } + case class Partition[A](override val underlying: Iterator[A], p: A => Boolean, lookahead: ArrayBuffer[A], dual: ArrayBuffer[A]) extends Iterator[A] { + def distribute() = { + val elem = underlying.next + (if (p(elem)) lookahead else dual) += elem + } + final def hasNext: Boolean = + !lookahead.isEmpty || underlying.hasNext && { distribute(); hasNext } + final def next = + if (hasNext) { + val r = lookahead.head + lookahead.trimStart(1) + r + } else Iterator.nextOnEmpty + } + case class Drop[A](override val underlying: Iterator[A], n: Int) extends Iterator[A] { + var toSkip = n + def hasNext: Boolean = underlying.hasNext && ( + toSkip == 0 || { underlying.next; toSkip -= 1; hasNext }) + def next = if (hasNext) underlying.next else nextOnEmpty + override def remaining = (underlying.remaining - toSkip) max -1 + } + case class Zip[A, B](override val underlying: Iterator[A], other: Iterator[B]) extends Iterator[(A, B)] { + def hasNext = underlying.hasNext && other.hasNext + def next = (underlying.next, other.next) + override def remaining = underlying.remaining min other.remaining + } + case class Reverse[A](override val underlying: RandomAccessIterator[A]) extends RandomAccessIterator[A] { + def apply(n: Int) = underlying.apply(underlying.limit - 1 - n) + def limit = underlying.remaining + } + } + + trait RandomAccessIterator[+A] extends Iterator[A] { self => + def apply(n: Int): A + def limit: Int + var start = 0 + override def remaining = (limit - start) max 0 + def hasNext = start < limit + def next: A = { val r = this(start); start += 1; r } + override def drop(n: Int): Iterator[A] = { start += (n max 0); this } + override def reverse: Iterator[A] = new Iterator.Reverse(this) + } +} + diff --git a/tests/disabled/pos/flowops.scala b/tests/disabled/pos/flowops.scala new file mode 100644 index 000000000..6aead26be --- /dev/null +++ b/tests/disabled/pos/flowops.scala @@ -0,0 +1,31 @@ +object Test { + import language.higherKinds + + class NotUsed + + trait FO[+Out, +Mat] { self => + type Repr[+O] <: FO[O, Mat] { + type Repr[+OO] = self.Repr[OO] + } + def map[T](f: Out => T): Repr[T] = ??? + } + + class Source[+O, +M] extends FO[O, M] { + type Repr[+OO] <: Source[OO, M] + } + + class Flow[-I, +O, +M] extends FO[O, M] { + type Repr[+OO] <: Flow[I, OO, M] + } + + implicit class x[O, M, F[o, m] <: FO[o, m]](val f: F[O, M]) extends AnyVal { + def xx(i: Int): f.Repr[O] = f.map(identity) + } + + type IntFlow[O, M] = Flow[Int, O, M] + + val s1 = new Source[Int, NotUsed].xx(12) + val s2: Source[Int, NotUsed] = s1 + val f1 = x[Int, NotUsed, IntFlow](new Flow[Int, Int, NotUsed]).xx(12) + val f2: Flow[Int, Int, NotUsed] = f1 +} diff --git a/tests/disabled/pos/flowops1.scala b/tests/disabled/pos/flowops1.scala new file mode 100644 index 000000000..649a9b18c --- /dev/null +++ b/tests/disabled/pos/flowops1.scala @@ -0,0 +1,39 @@ +object Test { + class NotUsed + + trait FO[type +Out, type +Mat] { self => + type Repr <: FO[Mat = self.Mat] { + type Repr = self.Repr + } + def map[T](f: Out => T): Repr[Out = T] = ??? + } + + class Source[type +Out, type +Mat] extends FO[Out, Mat] { self => + type Repr <: Source[Mat = self.Mat] + } + + class Flow[type -In, type +Out, type +Mat] extends FO[Out, Mat] { self => + type Repr <: Flow[In = self.In, Mat = self.Mat] + } + + implicit class x[O, M, F <: FO](val f: F[Out = O, Mat = M]) extends AnyVal { + def xx(i: Int): f.Repr[Out = O] = f.map(identity) + } + + class xalt[O, M, F <: FO](val f: F[Out = O, Mat = M]) extends AnyVal { + def xx(i: Int): FO[Out = O, Mat = M] = ??? + } + + val s1 = new Source[Int, NotUsed].xx(12) + val s2: Source[Int, NotUsed] = s1 + val f1 = x[Int, NotUsed, Flow[In = Int]](new Flow[Int, Int, NotUsed]).xx(12) + val f2: Flow[Int, Int, NotUsed] = f1 + + + val f3 = x(new Flow[Int, Int, NotUsed]).xx(12) + val f4: Flow[Int, Int, NotUsed] = f3 + val f5 = new Flow[Int, Int, NotUsed].xx(12) + val f6: Flow[Int, Int, NotUsed] = f5 + val f7 = new xalt(new Flow[Int, Int, NotUsed]).xx(12) + val f8: FO[Int, NotUsed] = f7 +} diff --git a/tests/disabled/pos/hk-named.scala b/tests/disabled/pos/hk-named.scala new file mode 100644 index 000000000..5f2cb6c74 --- /dev/null +++ b/tests/disabled/pos/hk-named.scala @@ -0,0 +1,58 @@ +import language.higherKinds + +object hk0 { + + trait Lambda[type Elem] + + abstract class Functor[F <: Lambda] { + def map[A, B](f: A => B): F[Elem = A] => F[Elem = B] + } + + object test1 { + class ListT[T] extends Lambda[T] + + val ml: Functor[ListT] = ??? + val mx = ml + var xs: ListT[Int] = ??? + var ys: ListT { type Elem = Int } = xs + xs = ys + val mm: (Int => Boolean) => ListT[Int] => ListT[Boolean] = mx.map[Int, Boolean] + val mm2: (Int => Boolean) => ListT[Int] => ListT[Boolean] = mx.map + } +} + + +object higherKinded { + + type Untyped = Null + + class Tree[type -Attr >: Untyped] { + type ThisType <: Tree + def withString(s: String): ThisType[Attr = String] = withString(s) + } +/* + class Ident[-Attr >: Untyped] extends Tree[Attr] { + type ThisType = Ident + } + + val id = new Ident[Integer] + + val y = id.withString("abc") + + val z: Ident[String] = y + + val zz: tpd.Tree = y + + abstract class Instance[T >: Untyped] {g + type Tree = higherKinded.Tree[T] + } + + object tpd extends Instance[String] + + def transform(tree: Tree[String]) = { + val tree1 = tree.withString("") + tree1: Tree[String] + } +*/ +} + diff --git a/tests/disabled/pos/named-params.scala b/tests/disabled/pos/named-params.scala new file mode 100644 index 000000000..3fab24cd2 --- /dev/null +++ b/tests/disabled/pos/named-params.scala @@ -0,0 +1,90 @@ +package namedparams + +class C[type Elem, type Value](val elem: Elem) { + def toVal: Elem = ??? +} + +class D[type Elem, V](elem: Elem) extends C[Elem, V](elem) + +object Test { + val c = new C[String, String]("A") { + override def toVal = elem + } + val x: c.Elem = c.elem + + val c2: C { type Elem = String } = c + + val c3 = new C[Elem = String, Value = Int]("B") + val c4 = new C[Elem = String]("C") + val x2: c2.Elem = c2.elem + + def d1[E, V](x: E) = new D[E, V](x) + def d2[E, V](x: E) = new C[Elem = E, Value = V](x) + + val y1 = d1[Int, String](1) + val y2 = d1[E = Int](2) + val y3 = d1[V = String](3) + val z1 = d2[E = Int, V = String](1) + val z2 = d2[V = String, E = Int](1) + val z3 = d2[E = Int](1) + val z4 = d2[V = Int]("AAA") + val z5 = d2[E = Int][V = String](1) + +// Testing type inference + + def f[X <: C](x: X[Int, Int]): X[String, String] = ??? + val arg1: C[Int, Int] = ??? + val res1 = f(arg1) + val chk1: C[String, String] = res1 + + class C1[type Elem, type Value](x: Elem) extends C[Elem, Value](x) + class CC extends C1[Int, Int](1) + val arg2: CC = ??? + val res2 = f(arg2) + val chk2: C[String, String] = res2 + + class D1[type Elem, type Value](x: Elem) extends C[Elem, Value](x) + class DD extends D1[Int, Int](2) + val arg3: CC & DD = ??? + val res3 = f(arg3) + val chk3: (C1 & D1) { type Elem = String; type Value = String } = res3 + val arg4: CC | DD = ??? + val res4 = f(arg4) + val chk4: C[String, String] = ??? + + class CX[type Elem](x: Elem) extends C1[Elem, Int](x) + class DX[type Value]() extends D1[Int, Value](2) + val arg5: CX[Int] & DX[Int] = ??? + val res5 = f(arg5) + val chk5: (C1 & D1) { type Elem = String; type Value = String } = res5 + val chk6: C1[String, String] & D1[String, String] = chk5 + val chk7: (C1 & D1) { type Elem = String; type Value = String } = chk6 +} + +// Adapted from i94-nada, somewhat non-sensical +trait Test1 { + trait Monad[type Elem] { + def unit: Elem + } + sealed abstract class Either[A,B] + case class Left[A,B](unit: A) extends Either[A,B] with Monad[A] + case class Right[A,B](unit: B) extends Either[A,B] with Monad[B] + def flatMap[X,Y,M <: Monad](m: M[Elem = X], f: X => M[Elem = Y]): M[Elem = Y] = f(m.unit) + val res = flatMap(Left(1), {x: Int => Left(x)}) + val chk: Either[Int, Nothing] & Monad & Product1[Int] = res +} + +// Adapted from i94-nada, this time with more sense +trait Test2 { + trait Monad[type Elem] { + def unit: Elem + } + sealed abstract class Either[A,B] + case class Left[type Elem, B](unit: Elem) extends Either[Elem,B] with Monad[Elem] + case class Right[A, type Elem](unit: Elem) extends Either[A,Elem] with Monad[Elem] + def flatMap[X,Y,M <: Monad](m: M[Elem = X], f: X => M[Elem = Y]): M[Elem = Y] = f(m.unit) + val res = flatMap(Left(1), {x: Int => Left(x)}) + val chk: Left[Int, Nothing] = res +} + + |