Skip to content

Instantly share code, notes, and snippets.

@dylemma
Last active August 29, 2015 14:21
Show Gist options
  • Select an option

  • Save dylemma/42630a183b604ca72029 to your computer and use it in GitHub Desktop.

Select an option

Save dylemma/42630a183b604ca72029 to your computer and use it in GitHub Desktop.
Numbers represented as types in scala. Because you can.
/** You can represent numbers as types. Why? Because you can!
*/
object TypesafeNumbers extends App {
println(Number[E2[`2`] + E1[`4`] + `6`])
println(Number[`8` ~ `6` ~ `7` ~ `5` ~ `3` ~ `0` ~ `9`])
}
// raw digits
trait `0`
trait `1`
trait `2`
trait `3`
trait `4`
trait `5`
trait `6`
trait `7`
trait `8`
trait `9`
// type for numbers times a power of 10
class E1[D: Number]
class E2[D: Number]
// type for the sum of two numbers
class +[Left: Number, Right: Number]
// type for (Left*10) + Right
class ~[Left: Number, Right: Number]
// typeclass for getting the value of a number type
trait Number[T] extends Any { def value: Int }
// just a helper for the values of digits
class RawNumber[T](val value: Int) extends AnyVal with Number[T]
object Number {
implicit def `0value` = new RawNumber[`0`](0)
implicit def `1value` = new RawNumber[`1`](1)
implicit def `2value` = new RawNumber[`2`](2)
implicit def `3value` = new RawNumber[`3`](3)
implicit def `4value` = new RawNumber[`4`](4)
implicit def `5value` = new RawNumber[`5`](5)
implicit def `6value` = new RawNumber[`6`](6)
implicit def `7value` = new RawNumber[`7`](7)
implicit def `8value` = new RawNumber[`8`](8)
implicit def `9value` = new RawNumber[`9`](9)
implicit def e1value[T: Number]: Number[E1[T]] = new Number[E1[T]] {
def value: Int = implicitly[Number[T]].value * 10
}
implicit def e2value[T: Number] = new Number[E2[T]] {
def value = implicitly[Number[T]].value * 100
}
// +[A, B] == A + B
implicit def `+value`[A: Number, B: Number] = new Number[A + B] {
def value = implicitly[Number[A]].value + implicitly[Number[B]].value
}
implicit def `~value`[A: Number, B: Number] = new Number[A ~ B] {
def value = implicitly[Number[A]].value * 10 + implicitly[Number[B]].value
}
// lets you do `Number[some number type]` to get an Int
def apply[N: Number] = implicitly[Number[N]].value
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment