Skip to content

Instantly share code, notes, and snippets.

@pr1001
Created November 14, 2011 00:33
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 pr1001/1362971 to your computer and use it in GitHub Desktop.
Save pr1001/1362971 to your computer and use it in GitHub Desktop.
Some experiments with natural numbers in Scala _without_ type class wizardry. As long at you use Nat() you are guaranteed a non-negative natural number.
scala> import Nat._
import Nat._
scala> Nat(1) to 5
res0: Option[IndexedSeq[Nat.Nat]] = Some(Vector(1N, 2N, 3N, 4N, 5N))
scala> Nat(1) + 5
res1: Option[Nat.Nat] = Some(6N)
scala> Nat(1) - 5
res2: Option[Nat.Nat] = None
scala> Nat(1) * 5
res3: Option[Nat.Nat] = Some(5N)
scala> Nat(1) / 5
res4: Option[Nat.Nat] = Some(0N)
scala> res4.get == Zero
res5: Boolean = true
scala> Nat(-1) to Nat(-7)
res6: Option[IndexedSeq[Nat.Nat]] = None
scala> Nat(1) to Nat(-7)
res7: Option[IndexedSeq[Nat.Nat]] = None
scala> Nat(-1) to Nat(7)
res8: Option[IndexedSeq[Nat.Nat]] = None
object Nat {
object Zero extends Nat(0)
class Nat(val number: Int) {
def to(n: Nat): Option[IndexedSeq[Nat]] = if(number <= n.number) Some((number to n.number).flatMap(apply(_))) else None
def +(n: Nat): Nat = new Nat(number + n.number)
def +(n: Int): Option[Nat] = this.+(apply(n))
def +(n: Option[Nat]): Option[Nat] = n.map(this + _)
def -(n: Nat): Option[Nat] = n.number match {
case i if number > i => Some(new Nat(number - i))
case i if number == i => Some(Zero)
case _ => None
}
def -(n: Int): Option[Nat] = this.-(apply(n))
def -(n: Option[Nat]): Option[Nat] = n.flatMap(this - _)
def *(n: Nat): Nat = if (this == Zero || n == Zero) Zero else new Nat(number * n.number)
def *(n: Int): Option[Nat] = this.*(apply(n))
def *(n: Option[Nat]): Option[Nat] = n.map(this * _)
def /(n: Nat): Option[Nat] = {
if (n != Zero) {
if (this == Zero || number / n.number == 0) {
Some(Zero)
} else {
Some(new Nat(number / n.number))
}
} else {
None
}
}
def /(n: Int): Option[Nat] = this./(apply(n))
def /(n: Option[Nat]): Option[Nat] = n.flatMap(this / _)
override def toString: String = number + "N"
}
def apply(n: Int): Option[Nat] = n match {
case 0 => Some(Zero)
case i if i > 0 => Some(new Nat(i))
case _ => None
}
def unapply(n: Int): Option[Nat] = apply(n)
implicit def shadow(number: Option[Nat]): shadowNat = new shadowNat(number)
class shadowNat(number: Option[Nat]) {
def to(n: Int): Option[IndexedSeq[Nat]] = for {
n2 <- apply(n)
seq <- number to n2
} yield seq
def to(n: Nat): Option[IndexedSeq[Nat]] = number.flatMap(_ to n)
def to(n: Option[Nat]): Option[IndexedSeq[Nat]] = number.flatMap(n1 => n.flatMap(n2 => n1 to n2))
def +(n: Int): Option[Nat] = number.flatMap(_ + n)
def +(n: Nat): Option[Nat] = number.map(_ + n)
def +(n: Option[Nat]): Option[Nat] = number.flatMap(_ + n)
def -(n: Int): Option[Nat] = this.-(apply(n))
def -(n: Nat): Option[Nat] = number.flatMap(_ - n)
def -(n: Option[Nat]): Option[Nat] = number.flatMap(_ - n)
def *(n: Int): Option[Nat] = this.*(apply(n))
def *(n: Nat): Option[Nat] = number.map(_ * n)
def *(n: Option[Nat]): Option[Nat] = number.flatMap(_ * n)
def /(n: Int): Option[Nat] = this./(apply(n))
def /(n: Nat): Option[Nat] = number.flatMap(_ / n)
def /(n: Option[Nat]): Option[Nat] = number.flatMap(_ / n)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment