Created
August 26, 2015 14:44
-
-
Save erikerlandson/6c40f53eb76c6fc5e749 to your computer and use it in GitHub Desktop.
Testing ability to constrain type variable bindings to emulate unit algebra
This file contains 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
object commutative { | |
import scala.language.implicitConversions | |
sealed class =!=[A,B] | |
trait LowerPriorityImplicits { | |
implicit def equal[A]: =!=[A, A] = sys.error("should not be called") | |
} | |
object =!= extends LowerPriorityImplicits { | |
implicit def nequal[A,B](implicit same: A =:= B = null): =!=[A,B] = | |
if (same != null) sys.error("should not be called explicitly with same type") | |
else new =!=[A,B] | |
} | |
trait A | |
case object A extends A | |
trait B | |
case object B extends B | |
trait C | |
case object C extends C | |
case class UnitValue1[U1](value: Double) { | |
def +(that: UnitValue1[U1]) = UnitValue1[U1](this.value + that.value) | |
// sharing 0 terms | |
def *[U2](that: UnitValue1[U2]): UnitValue2[U1, U2] = { | |
implicitly[U2 =!= U1] | |
UnitValue2[U1, U2](this.value * that.value) | |
} | |
def *[U2, U3](that: UnitValue2[U2, U3]): UnitValue3[U1, U2, U3] = { | |
implicitly[U2 =!= U1] | |
implicitly[U3 =!= U1] | |
implicitly[U3 =!= U2] | |
UnitValue3[U1, U2, U3](this.value * that.value) | |
} | |
// sharing 1 term | |
def *(that: UnitValue1[U1]): UnitValue1[U1] = UnitValue1[U1](this.value * that.value) | |
def *[U2](that: UnitValue2[U1, U2]): UnitValue2[U1, U2] = { | |
implicitly[U2 =!= U1] | |
UnitValue2[U1, U2](this.value * that.value) | |
} | |
def *[U2, U3](that: UnitValue3[U1, U2, U3]): UnitValue3[U1, U2, U3] = { | |
implicitly[U2 =!= U1] | |
implicitly[U3 =!= U1] | |
implicitly[U3 =!= U2] | |
UnitValue3[U1, U2, U3](this.value * that.value) | |
} | |
} | |
case class UnitValue2[U1, U2](value: Double) { | |
implicitly[U1 =!= U2] | |
def +(that: UnitValue2[U1, U2]) = UnitValue2[U1, U2](this.value + that.value) | |
// sharing 0 terms | |
def *[U3](that: UnitValue1[U3]): UnitValue3[U1, U2, U3] = { | |
implicitly[U3 =!= U1] | |
implicitly[U3 =!= U2] | |
UnitValue3[U1, U2, U3](this.value * that.value) | |
} | |
// sharing 1 term | |
// Scala calls these duplicates, because it can't understand that U1 =!= U2. | |
def *(that: UnitValue1[U1]): UnitValue2[U1, U2] = { | |
UnitValue2[U1, U2](this.value * that.value) | |
} | |
def *(that: UnitValue1[U2]): UnitValue2[U1, U2] = { | |
UnitValue2[U1, U2](this.value * that.value) | |
} | |
// Scala calls these duplicates, because it can't understand that U1 =!= U2. | |
def *[U3](that: UnitValue2[U1, U3]): UnitValue3[U1, U2, U3] = { | |
implicitly[U3 =!= U1] | |
implicitly[U3 =!= U2] | |
UnitValue3[U1, U2, U3](this.value * that.value) | |
} | |
def *[U3](that: UnitValue2[U2, U3]): UnitValue3[U1, U2, U3] = { | |
implicitly[U3 =!= U1] | |
implicitly[U3 =!= U2] | |
UnitValue3[U1, U2, U3](this.value * that.value) | |
} | |
// sharing 2 terms | |
def *(that: UnitValue2[U1, U2]): UnitValue2[U1, U2] = UnitValue2[U1, U2](this.value * that.value) | |
} | |
object UnitValue2 { | |
implicit def uv2Reorder01[U2, U1](uv2: UnitValue2[U2, U1]) = UnitValue2[U1, U2](uv2.value) | |
} | |
case class UnitValue3[U1, U2, U3](value: Double) { | |
def +(that: UnitValue3[U1, U2, U3]) = UnitValue3[U1, U2, U3](this.value + that.value) | |
} | |
object UnitValue3 { | |
implicit def uv3Reorder01[U1, U3, U2](uv3: UnitValue3[U1, U3, U2]) = | |
UnitValue3[U1, U2, U3](uv3.value) | |
implicit def uv3Reorder02[U2, U1, U3](uv3: UnitValue3[U2, U1, U3]) = | |
UnitValue3[U1, U2, U3](uv3.value) | |
implicit def uv3Reorder03[U2, U3, U1](uv3: UnitValue3[U2, U3, U1]) = | |
UnitValue3[U1, U2, U3](uv3.value) | |
implicit def uv3Reorder04[U3, U1, U2](uv3: UnitValue3[U3, U1, U2]) = | |
UnitValue3[U1, U2, U3](uv3.value) | |
implicit def uv3Reorder05[U3, U2, U1](uv3: UnitValue3[U3, U2, U1]) = | |
UnitValue3[U1, U2, U3](uv3.value) | |
} | |
val uv1a = UnitValue1[A](2) | |
val uv1b = UnitValue1[B](3) | |
val uv1c = UnitValue1[C](4) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment