Skip to content

Instantly share code, notes, and snippets.

@OlivierBlanvillain
Created March 26, 2018 16:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save OlivierBlanvillain/d314ddbcb640e2ce5604d860b5073008 to your computer and use it in GitHub Desktop.
Save OlivierBlanvillain/d314ddbcb640e2ce5604d860b5073008 to your computer and use it in GitHub Desktop.
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