Unfortunately, this is not something you could easily check at compile time. Well, at least not if you don't restrict operations on your type. If your goal is to simply verify that the numeric literal is nonzero, you can easily write a macro that checks this property. However, I see no use in proving that the negative literal is really negative.
The problem is not a limitation of Scala, which has a very strong type system, but the fact that (in a rather complicated program) you cannot statically know all the possible states. However, you can try to override the set of all possible states.
Consider an example of introducing a type of NegativeNumber
, which only ever represents a negative number. For simplicity, we define only one operation: plus
.
Suppose you would only allow the addition of several NegativeNumber
, then a type system could be used to ensure that each NegativeNumber
indeed a negative number. But this seems really restrictive, so a useful example will certainly allow us to add at least NegativeNumber
and a generic Int
.
What if you have the expression val z: NegativeNumber = plus(x, y)
, where you do not know the values ββof x
and y
statically (maybe they are returned by the function). How do you know (statically) that z
is indead a negative number?
The approach to solving the problem will be the introduction of an abstract interpretation that should be performed on the representation of your program (source code, abstract syntax tree, ...).
For example, you can define a Lattice for numbers with the following elements:
Top
: all numbers+
: all positive numbers0
: number 0
-
: all negative numbersBottom
: not a number - just entered that each pair of elements has the largest lower bound
with order Top
> ( +
, 0
, -
)> Bottom
.

Then you will need to define the semantics for your operations. Taking the commutative plus
method from our example:
plus(Bottom, something)
always Bottom
, since you cannot calculate something using invalid numbers.plus(Top, x)
, x != Bottom
always Top
, because adding an arbitrary number to any number is always an arbitrary numberplus(+, +)
+
, since adding two positive numbers will always give a positive numberplus(-, -)
-
, since adding two negative numbers will always give a negative numberplus(0, x)
, x != Bottom
x
, since 0
is the addition identity.
The problem is
plus - +
will be Top
, because you do not know a positive or negative number.
To be statically safe, you need to take a conservative approach and prohibit such an operation.
There are more complex numerical domains , but in the end they all suffer from the same problem: they represent an excessive approximation of the actual state of the program.
I would say that the problem is similar to integer overflow / underflow: As a rule, you donβt know if the operation statically shows overflow - you only know this at runtime.