I was making a own fixed-size vector class and this code was rejected
import scala.compiletime.ops.int._
enum Tensor1[Dim <: Int, +T]:
case Empty extends Tensor1[0, Nothing]
case Cons[N <: Int, A](head: A, tail: Tensor1[N, A]) extends Tensor1[S[N], A]
def ::[SuperT >: T](operand: SuperT): Tensor1[Dim + 1, SuperT] = Cons(operand, this)
with this message:
[error] Tree: Tensor1.Cons.apply[Dim, SuperT](operand, this)
[error] I tried to show that
[error] Tensor1.Cons[Dim, SuperT]
[error] conforms to
[error] Tensor1[Dim + (1 : Int), SuperT]
[error] but the comparison trace ended with `false`:
but when I changed Dim + 1 to S[Dim] in definition of ::, it works.
def ::[SuperT >: T](operand: SuperT): Tensor1[S[Dim], SuperT] = Cons(operand, this)
Why this happens? Are S and + 1 different?
Yes,
Sand+ 1are indeed different.They are implemented in compiler internals.
Scala is not an actual theorem prover. It allows you to prove theorems but doesn't prove theorems for you. Scala knows that
10 + 1or1 + 10areS[10]but doesn't know thatn + 1or1 + nareS[n]Even when
Sand+are implemented inductivelyit's obvious that
_1 + n =:= S[n]but not obvious thatn + _1 =:= S[n](this is a theorem to be proved)If you define addition inductively with respect to the 2nd argument
then vice versa
n + _1 =:= S[n]becomes obvious but_1 + n =:= S[n]has to be provedHow to define induction on natural numbers in Scala 2.13?