Is it possible to restrict Int by creating something like PositiveInt and have compile-time checks in Scala?

后端 未结 4 1217
失恋的感觉
失恋的感觉 2021-01-07 18:16

Is it possible to create a restricted Int such as PositiveInt and have compile-time checks for it? In other words is it possible to define a method such as:

4条回答
  •  清歌不尽
    2021-01-07 18:58

    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)
    

提交回复
热议问题