Created
March 26, 2018 16:31
-
-
Save OlivierBlanvillain/d314ddbcb640e2ce5604d860b5073008 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import reflect.ClassTag | |
object playground { | |
/* All combinations of | |
* - trait / trait with common / extension trait | |
* - extending class / extension | |
* - monomorphic / generic implementation | |
*/ | |
// trait HasLength { | |
// def length: Int | |
// } | |
trait HasLength { | |
def length: Int | |
} | |
trait HasLength_TC[T] { | |
def length(self: T): Int | |
} | |
object HasLength { | |
def impl[T](implicit ev: HasLength_TC[T]) = ev | |
} | |
implicit class HasLengthOps[T](self: T)(implicit ev: HasLength_TC[T]) { | |
def length: Int = ev.length(self) | |
} | |
// trait HasBoundedLength extends HasLength { | |
// common def limit: Int | |
// } | |
trait HasBoundedLength extends HasLength | |
trait HasBoundedLengthCommon { def limit: Int } | |
trait HasBoundedLength_TC[T] extends HasLength_TC[T] { | |
def limit: Int | |
} | |
object HasBoundedLength { | |
def impl[T](implicit ev: HasBoundedLength_TC[T]) = ev | |
} | |
// extension trait HasBoundedLengthX extends HasBoundedLength { | |
// common def longest: This | |
// } | |
trait HasBoundedLengthX extends HasBoundedLength | |
trait HasBoundedLengthX_TC[T] extends HasBoundedLength_TC[T] { | |
def longest: T | |
} | |
object HasBoundedLengthX { | |
def impl[T](implicit ev: HasBoundedLengthX_TC[T]) = ev | |
} | |
// class C1(xs: Array[Int]) extends HasLength { | |
// def length = xs.length | |
// } | |
class C1(xs: Array[Int]) extends HasLength { | |
def length = xs.length | |
} | |
object C1 { | |
implicit def $1 = new HasLength_TC[C1] { def length(self: C1): Int = self.length } | |
} | |
// class CG1[T](xs: Array[T]) extends HasLength { | |
// def length = xs.length | |
// } | |
class CG1[T](xs: Array[T]) extends HasLength { | |
def length = xs.length | |
} | |
trait CG1Common { | |
implicit def $1[T] = new HasLength_TC[CG1[T]] { def length(self: CG1[T]): Int = self.length } | |
} | |
object CG1 extends CG1Common | |
// class C2(xs: Array[Int]) extends C1(xs) with HasBoundedLength { | |
// common def limit = 100 | |
// } | |
class C2(xs: Array[Int]) extends C1(xs) with HasBoundedLength | |
trait C2Common extends HasBoundedLengthCommon { | |
def limit = 100 | |
implicit def $1 = new HasBoundedLength_TC[C2] { | |
def length(self: C2): Int = self.length | |
def limit = C2.limit | |
} | |
} | |
object C2 extends C2Common | |
// class CG2[T: ClassTag](xs: Array[T]) extends CG1[T](xs) with HasBoundedLength { | |
// common def limit = 100 | |
// } | |
class CG2[T](xs: Array[T]) extends CG1[T](xs) with HasBoundedLength | |
trait CG2Common extends CG1Common { | |
val limit = 100 | |
implicit def $2[T] = new HasBoundedLength_TC[CG2[T]] { | |
def length(self: CG2[T]): Int = self.length | |
def limit = CG2.limit | |
} | |
} | |
object CG2 extends CG2Common | |
// final class C3(xs: Array[Int]) extends C2(xs) with HasBoundedLengthX { | |
// common def longest = new C3(new Array[Int](limit)) | |
// } | |
class C3(xs: Array[Int]) extends C2(xs) | |
trait C3Common extends C2Common { | |
def longest = new C3(new Array[Int](limit)) | |
implicit def $3 = new HasBoundedLengthX_TC[C3] { | |
def length(self: C3): Int = self.length | |
def longest: C3 = new C3(new Array[Int](limit)) | |
def limit = 100 | |
} | |
} | |
object C3 extends C3Common | |
// final class CG3[T: ClassTag](xs: Array[T]) extends CG2[T](xs) with HasBoundedLengthX { | |
// common def longest = new CG3(new Array[T](limit)) | |
// } | |
class CG3[T](xs: Array[T]) extends CG2[T](xs) | |
trait CG3Common { | |
implicit def $4[T: ClassTag] = new HasBoundedLengthX_TC[CG3[T]] { | |
def length(self: CG3[T]): Int = self.length | |
def longest: CG3[T] = new CG3(new Array[T](limit)) | |
def limit = 100 | |
} | |
} | |
object CG3 extends CG3Common | |
// class D1(val xs: Array[Int]) | |
// class DG1[T](val xs: Array[T]) | |
// class D2(val xs: Array[Int]) | |
// class DG2[T](val xs: Array[T]) | |
// class D3(val xs: Array[Int]) | |
// class DG3[T](val xs: Array[T]) | |
class D1(val xs: Array[Int]) | |
class DG1[T](val xs: Array[T]) | |
class D2(val xs: Array[Int]) | |
class DG2[T](val xs: Array[T]) | |
class D3(val xs: Array[Int]) | |
class DG3[T](val xs: Array[T]) | |
// extension DHasLength for D1 : HasLength { | |
// def length = xs.length | |
// } | |
implicit def DHasLength = new HasLength_TC[D1] { def length(self: D1) = self.xs.length } | |
// extension DGHasLength[T] for DG1[T] : HasLength { | |
// def length = xs.length | |
// } | |
implicit def DGHasLength[T] = new HasLength_TC[DG1[T]] { def length(self: DG1[T]) = self.xs.length } | |
// extension DHasBoundedLength for D2 : HasBoundedLength { | |
// def length = xs.length | |
// common def limit = 100 | |
// } | |
implicit def DHasBoundedLength = new HasBoundedLength_TC[D2] { | |
def length(self: D2) = self.xs.length | |
def limit = 100 | |
} | |
// extension DGHasBoundedLength[T] for DG2[T] : HasBoundedLength { | |
// def length = xs.length | |
// common def limit = 100 | |
// } | |
implicit def DGHasBoundedLength[T] = new HasBoundedLength_TC[DG2[T]] { | |
def length(self: DG2[T]) = self.xs.length | |
def limit = 100 | |
} | |
// extension DHasBoundedLengthX for D3 : HasBoundedLengthX { | |
// def length = xs.length | |
// common def limit = 100 | |
// common def longest = new D3(new Array[Int](limit)) | |
// } | |
implicit def DHasBoundedLengthX = new HasBoundedLengthX_TC[D3] { | |
def length(self: D3) = self.xs.length | |
def limit = 100 | |
def longest = new D3(new Array[Int](limit)) | |
} | |
// extension DGHasBoundedLengthX[T](implicit tag: ClassTag[T]) for DG3[T] : HasBoundedLengthX { | |
// def length = xs.length | |
// common def limit = 100 | |
// common def longest = new DG3(new Array[T](limit)) | |
// } | |
implicit def DGHasBoundedLengthX[T: ClassTag] = new HasBoundedLengthX_TC[DG3[T]] { | |
def length(self: DG3[T]) = self.xs.length | |
def limit = 100 | |
def longest = new DG3(new Array[T](limit)) | |
} | |
// def length[T : HasLength](x: T) = x.length | |
// def lengthOK[T : HasBoundedLength](x: T) = | |
// x.length < x.common.limit | |
// def lengthOKX[T : HasBoundedLengthX](x: T) = | |
// x.length < HasBoundedLengthX.impl[T].limit | |
// def longestLengthOK[T : HasBoundedLengthX](implicit tag: ClassTag[T]) = { | |
// val impl = HasBoundedLengthX.impl[T] | |
// impl.longest.length < impl.limit | |
// } | |
def length[T : HasLength_TC](x: T) = x.length | |
def lengthOK[T : HasBoundedLength_TC](x: T) = | |
x.length < HasBoundedLength.impl[T].limit | |
def lengthOKX[T : HasBoundedLengthX_TC](x: T) = | |
x.length < HasBoundedLengthX.impl[T].limit | |
def longestLengthOK[T : HasBoundedLengthX_TC](x: T) = { | |
val impl = HasBoundedLengthX.impl[T] | |
impl.longest.length < impl.limit | |
} | |
val xs = Array(1, 2, 3) | |
val c1 = new C1(xs) | |
val cg1 = new CG1(xs) | |
val c2 = new C2(xs) | |
val cg2 = new CG2(xs) | |
val c3 = new C3(xs) | |
val cg3 = new CG3(xs) | |
val d1 = new D1(xs) | |
val dg1 = new DG1(xs) | |
val d2 = new D2(xs) | |
val dg2 = new DG2(xs) | |
val d3 = new D3(xs) | |
val dg3 = new DG3(xs) | |
length(c1) | |
length(cg1) | |
length(c2) | |
length(cg2) | |
length(c3) | |
length(cg3) | |
length(d1) | |
length(dg1) | |
length(d2) | |
length(dg2) | |
length(d3) | |
length(dg3) | |
lengthOK(c2) | |
lengthOK(cg2) | |
lengthOK(c3) | |
lengthOK(cg3) | |
lengthOK(d2) | |
lengthOK(dg2) | |
lengthOK(d3) | |
lengthOK(dg3) | |
lengthOKX(c3) | |
lengthOKX(cg3) | |
lengthOKX(d3) | |
lengthOKX(dg3) | |
longestLengthOK(c3) | |
longestLengthOK(cg3) | |
longestLengthOK(d3) | |
longestLengthOK(cg3) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment