Skip to content

Instantly share code, notes, and snippets.

@rudogma
Last active June 24, 2017 12:09
Show Gist options
  • Save rudogma/12ebcdae41423a76a3f59b70ef28607e to your computer and use it in GitHub Desktop.
Save rudogma/12ebcdae41423a76a3f59b70ef28607e to your computer and use it in GitHub Desktop.
OverTagged: typelevel inheritance(like extend, but with tags on typelevel)
import org.scalatest.{FlatSpec, Matchers}
import shapeless.test.illTyped
import TestOverTagged2._
import supertagged.{OverTagged, Tag, Tagged, TaggedType, TaggedTypeF}
import scala.language.higherKinds
class TestOverTagged2 extends FlatSpec with Matchers {
"It" should "work" in {
val value = ClassF[Int](5)
val a = A[ClassF,Int](value)
val b = B[ClassF, Int](a)
val c = C[ClassF, Int](b)
testA(a)
testB(b)
testC(c)
testA(b)
testA(c)
testB(c)
illTyped("testC(a)","type mismatch;.+")
illTyped("testC(b)","type mismatch;.+")
illTyped("testB(a)","type mismatch;.+")
b.print shouldEqual "print B"
c.print shouldEqual "print B"
b.printOverrided shouldEqual "print B"
c.printOverrided shouldEqual "print C"
println("-parameterized")
}
def testA[T](a:A[ClassF, T]):Unit = {}
def testB[T](a:B[ClassF, T]):Unit = {}
def testC[T](a:C[ClassF, T]):Unit = {}
}
object TestOverTagged2 {
case class ClassF[T](value:T)
def A[F[_], T]:TaggedTypeF[F[T]] = TaggedTypeF[F[T]]
type A[F[_], T] = TaggedTypeF[F[T]]#Type
def B[F[_], T]:TaggedTypeF[A[F,T]] = TaggedTypeF[A[F,T]]
type B[F[_], T] = TaggedTypeF[A[F,T]]#Type
implicit class BOps[F[_],T](val __v:TaggedTypeF[A[F,T]]#Type) extends AnyVal {
def print:String = "print B"
def printOverrided:String = "print B"
}
def C[F[_], T]:TaggedTypeF[B[F,T]] = TaggedTypeF[B[F,T]]
type C[F[_], T] = TaggedTypeF[B[F,T]]#Type
implicit class COps[F[_],T](val __v:TaggedTypeF[B[F,T]]#Type) extends AnyVal {
def print:String = "print B"
def printOverrided:String = "print C"
}
}
import org.scalatest.{FlatSpec, Matchers}
import shapeless.test.illTyped
import TestOverTagged3._
import supertagged._
import scala.language.higherKinds
class TestOverTagged3 extends FlatSpec with Matchers {
"It" should "work" in {
val value = ClassF[Int](5)
val a = A[ClassF[Int]](value)
val b = B[ClassF[Int]](a)
val c = C[ClassF[Int]](b)
testA(a)
testB(b)
testC(c)
testA(b)
testA(c)
testB(c)
illTyped("testC(a)","type mismatch;.+")
illTyped("testC(b)","type mismatch;.+")
illTyped("testB(a)","type mismatch;.+")
b.print shouldEqual "print B"
c.print shouldEqual "print B"
b.printOverrided shouldEqual "print B"
c.printOverrided shouldEqual "print C"
println("-parameterized")
val value2 = ClassF[Long](5L)
val a2 = A[ClassF[Long]](value2)
val b2 = B[ClassF[Long]](a2)
val c2 = C[ClassF[Long]](b2)
testA(a2)
illTyped("testB(b2)","type mismatch;.+")
}
def testA[T](a:A[ClassF[T]]):Unit = {}
def testB(a:B[ClassF[Int]]):Unit = {}
def testC[T](a:C[ClassF[T]]):Unit = {}
}
object TestOverTagged3 {
case class ClassF[T](value:T)
def A[T]:TaggedTypeF[T] = TaggedTypeF[T]
type A[T] = TaggedTypeF[T]#Type
def B[T]:TaggedTypeF[A[T]] = TaggedTypeF[A[T]]
type B[T] = TaggedTypeF[A[T]]#Type
def C[T]:TaggedTypeF[B[T]] = TaggedTypeF[B[T]]
type C[T] = TaggedTypeF[B[T]]#Type
implicit class BOps[T](val __v:TaggedTypeF[A[T]]#Type) extends AnyVal {
def print:String = "print B"
def printOverrided:String = "print B"
}
implicit class COps[T](val __v:TaggedTypeF[B[T]]#Type) extends AnyVal {
def print:String = "print B"
def printOverrided:String = "print C"
}
}
import org.scalatest.{FlatSpec, Matchers}
import superquants._
import longprecision._
import time._
import length._
import render._
import shapeless.test.illTyped
import superquantstests.TestOverTagged._
import supertagged.{OverTagged, TaggedType}
class TestOverTagged extends FlatSpec with Matchers {
"It" should "work" in {
val a = A(5)
val b = B(a)
val c = C(b)
testA(a)
testB(b)
testC(c)
testA(b)
testA(c)
testB(c)
illTyped("testC(a)","type mismatch;.+")
illTyped("testC(b)","type mismatch;.+")
illTyped("testB(a)","type mismatch;.+")
b.print shouldEqual "print B"
c.print shouldEqual "print B"
b.printOverrided shouldEqual "print B"
c.printOverrided shouldEqual "print C"
}
def testA(a:A):Unit = {}
def testB(a:B):Unit = {}
def testC(a:C):Unit = {}
}
object TestOverTagged {
object A extends TaggedType[Int]
type A = A.Type
object B extends OverTagged(A){
implicit class BOps(val __v:Type) extends AnyVal {
def print:String = "print B"
def printOverrided:String = "print B"
}
}
type B = B.Type
object C extends OverTagged(B){
implicit class COps(val __v:Type) extends AnyVal {
def printOverrided:String = "print C"
}
}
type C = C.Type
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment