The other answers refer mostly to the issue of creating a "positive number" type that relates to a "number" type in a way the compiler can guarantee correctness. For example with dependent types you can proof that the implementation of functions like abs
are correct. You can't do that with scala.
You can, however, build a type that represents positive integers and nothing else. For example:
abstract class Pos {
def toInt: Int
}
case object Zero extends Pos {
def toInt: Int = 0
}
case class Next(x: Pos) extends Pos {
def toInt: Int = 1 + x.toInt
}
object Pos {
def apply(x: Int): Pos =
x match {
case n if (n < 0) => throw new IllegalArgumentException(s"$x is not a positive integer")
case 0 => Zero
case n => Next(Pos(n-1))
}
}
This is similar to what ziggystar proposed, with the difference that is the correctness of the type is guaranteed by its own construction, not by the constructor. That is, it is impossible to represent a negative number with this type.
This approach is likely not to be practical for your purposes. You either need to implement all the operations for it or piggyback to the Int value, which then is equivalent to just have a runtime check since you lose all type safety you won by representing positive integers in this way.
That is essentially what would happen in your example. Since Pos.apply
is not type safe, you cannot get a compile error in
myMethod(-5)