The inox documentation states the following
Inox provides the utility types TypedADTSort and TypedADTConstructor (see file inox/ast/Definitions.scala) that correspond to ADT definitions whose type parameters have been instantiated with concrete types. One can use these to access parameters/fields and enclosed expressions with instantiated types.
The following object contains the sorts and constructors necessary for modelling a mathematical field.
import inox._
import inox.trees.{forall => _, _}
import inox.trees.dsl._
import welder._
object Field {
/*
A non trivial field has elements different from zero.
We can further assume the existence of a nonzero element called one.
Any other element is of type notOne.
field -> zero
-> nonZero -> one
-> notOne
*/
val element = FreshIdentifier("element")
val zero = FreshIdentifier("zero")
val nonZero = FreshIdentifier("nonZero")
val one = FreshIdentifier("one")
val notOne = FreshIdentifier("notOne")
val elementADT = mkSort(element)()(Seq(zero, one, nonZero, notOne))
val nonZeroADT = mkConstructor(nonZero)()(Some(element)) {_ => Seq()}
val zeroADT = mkConstructor(zero)()(Some(element)) {_ => Seq()}
val oneADT = mkConstructor(one)()(Some(nonZero)) {_ => Seq()}
val notOneADT = mkConstructor(notOne)()(Some(nonZero)) {_ => Seq()}
val symbols = NoSymbols
.withADTs(Seq(elementADT, nonZeroADT, zeroADT, oneADT, notOneADT))
.withFunctions(Seq(/*Register functions*/))
val program = InoxProgram(Context.empty, symbols)
val theory = theoryOf(program)
import theory._
}
Now I introduce the sorts and constructs for modelling affine points of an elliptic curve.
import inox._
import inox.trees.{forall => _, _}
import inox.trees.dsl._
import welder._
object Curve {
val F: ADTType = T(Field.element)()
val affinePoint = FreshIdentifier("affinePoint")
val infinitePoint = FreshIdentifier("infinitePoint")
val finitePoint = FreshIdentifier("finitePoint")
val x = FreshIdentifier("x")
val y = FreshIdentifier("y")
val affinePointADT = mkSort(affinePoint)("F")(Seq(infinitePoint,finitePoint))
val infiniteADT = mkConstructor(infinitePoint)("F")(Some(affinePoint))(_ => Seq())
val finiteADT = mkConstructor(finitePoint)("F")(Some(affinePoint)){ case Seq(fT) =>
Seq(ValDef(x, fT), ValDef(y, fT))
}
val affine = TypedADTSort(affinePointADT,Seq(F))
val infinite = TypedADTConstructor(infiniteADT,Seq(F))
val finite = TypedADTConstructor(finiteADT,Seq(F))
val symbols = NoSymbols
.withADTs(Seq(affinePointADT, infiniteADT, finiteADT))
.withFunctions(Seq(/*Register functions here*/))
}
You can observe that at the end I'm using TypedADTSort
and TypedADTConstructor
to use the field elements as parameter instead of a generic parameter. I need this to talk about operations on field elements in the context of affine points.
Compile error
Compiling this gives an error of the type
could not find implicit value for parameter symbols: inox.trees.Symbols
[error] val affine = TypedADTSort(affinePointADT,Seq(F))
[error] ^
could not find implicit value for parameter symbols: inox.trees.Symbols
[error] val infinite = TypedADTConstructor(infiniteADT,Seq(F))
Why does this happen? What solutions are there?