How do I show that anything follows from a value of a type with no constructors in Scala? I would like to do a pattern match on the value and have Scala tell me that no patterns can match, but I am open for other suggestions. Here is a short example of why it would be useful.
Proving negatives
In Scala it is possible to define the natural numbers on a type level, e.g. with Peano encoding.
sealed trait Nat
sealed trait Zero extends Nat
sealed trait Succ[N <: Nat] extends Nat
From this we can define what it means for a number to be even. Zero is even, and any number two more than an even number is also even.
sealed trait Even[N <: Nat]
sealed case class Base() extends Even[Zero]
sealed case class Step[N <: Nat](evenN: Even[N]) extends Even[Succ[Succ[N]]]
From this we can show that e.g. two is even:
val `two is even`: Even[Succ[Succ[Zero]]] = Step(Base())
But I am unable to show that one is not even, even though the compiler can tell me that neither Base
nor Step
can inhabit the type.
def `one is odd`(impossible: Even[Succ[Zero]]): Nothing = impossible match {
case _: Base => ???
case _: Step[_] => ???
}
The compiler will happily tell me that none of the cases I've given are possible with the error pattern type is incompatible with expected type
, but leaving the match
block empty will be a compile error.
Is there any way to prove this constructively? If empty pattern matches is the way to go - I'd accept any version of Scala or even a macro or plugin, as long as I still get errors for empty pattern matches when the type is inhabited. Maybe I am barking up the wrong tree, is a pattern match the wrong idea - could EFQ be shown in some other way?
Note: Proving that one is odd could be done with another (but equivalent) definition of evenness - but that is not the point. A shorter example of why EFQ could be needed:
sealed trait Bottom
def `bottom implies anything`(btm: Bottom): Any = ???
Step
, shouldn't it extendEven[Succ[Succ[N]]]
? Otherwise, it's just a proof that 2 is even. – Landman