Modelling a class hierarchy in Inox - leon

I want to model the following Scala hierarchy in the Inox solver interface:
abstract class Element()
abstract class nonZero() extends Element
final case class Zero() extends Element
final case class One() extends nonZero()
final case class notOne() extends nonZero()
How can I model nonZero?
If I model it as an constructor
def mkConstructor(id: Identifier, flags: Flag*)
(tParamNames: String*)
(sort: Option[Identifier])
(fieldBuilder: Seq[TypeParameter] => Seq[ValDef]) = {
val tParams = tParamNames map TypeParameter.fresh
val tParamDefs = tParams map (TypeParameterDef(_))
val fields = fieldBuilder(tParams)
new ADTConstructor(id, tParamDefs, sort, fields, flags.toSet)
}
Then I'm not able to specify that it has other constructors extending it. Whereas if I model it as a sort:
def mkSort(id: Identifier, flags: Flag*)
(tParamNames: String*)
(cons: Seq[Identifier]) = {
val tParams = tParamNames map TypeParameter.fresh
val tParamDefs = tParams map (TypeParameterDef(_))
new ADTSort(id, tParamDefs, cons, flags.toSet)
}
Then I cannot specify that it is a subtype of Element.
Why do I need this for
I need this hierarchy because I need to state properties as this:
The set of non zero elements of the field with one, inverse and
multiplication by a non zero element forms a group.
I would need then some mechanism to generate a type to restrict the constructors of a sort, in this case, restrict the constructors of Element to One and notZeroOne(). In that case I would be modelling:
abstract class Element()
final case class Zero() extends Element
final case class One() extends Element()
final case class notZeroOne() extends Element()
What is the cleanest solution for this?

Unfortunately, the "class hierarchy" in Inox is limited to a single abstract parent with a sequence of concrete constructors (no subtyping between constructors is possible). This limitation reflects the limitation imposed on the theory of algebraic datatypes supported by the underlying SMT solvers.
If you want to state properties on non-zero elements, why don't you just use an implication of the form (elem !== Zero()) ==> someProperty? Note that in general, you can simulate the nonZero() type proposed above through a concrete predicate that exhaustively enumerates the allowed constructors. For example,
def nonZero(e: Expr): Expr = e.isInstOf(T(one)()) || e.isInstOf(T(notOne)())
Then you can state properties on non-zero elements by using nonZero(e) ==> property(e).

Related

How to properly register primitives and nulls in polymorphic serialization?

I need to set up a serialization/deserialization mechanism for a polymorphic class hierarchy that also includes primitives and nulls. There are container classes containing collections with polymorphic objects, primitives, and nulls. And, the subclasses for these objects are spread across modules (therefore sealed is not an option).
I have been reading through the kotlinx.serialization polymorphism docs trying to come up with a solution. I've been able to make some incremental progress by working through that tutorial but I seem to still be hitting a wall when I try to put everything together.
The code I am posting here is a minimal example that brings together everything I need. If I can get this example to work, that should cover everything I need for my real project. This example does run without error but introduces some unnecessary readability and efficiency issues.
All classes in my custom class hierarchy are serializable data classes. The outermost container object that needs to be serialized/deserialized is a map wrapper. This map has keys which are each an instance of one of these data classes. And the values of this map can be primitives, nulls, or instances of one of my data classes. I think my main challenge here is to include those primitives and nulls in my polymorphic serialization in a clean way.
The goal of my code below is to represent this problem in the simplest way possible and to serialize and deserialize one container object successfully.
There are two main issues in the code:
I've had to replace null with FakeNull. Without this, I get null cannot be cast to non-null type kotlin.Any. This will reduce the readability and simplicity of my code and I suspect it could decrease efficiency as well.
I've had to add StringClassSerializer and DoubleClassSerializer and wrapper classes. I would also need to add serializers like these for every primitive class. If I don't register these primitives as subclasses of Any, I get Class 'String' is not registered for polymorphic serialization in the scope of 'Any'.. And if I try to register them with their default serializers (like subclass(String::class, String.serializer())) I get Serializer for String of kind STRING cannot be serialized polymorphically with class discriminator.. The problem with using serializers like StringClassSerializer and wrappers like StringWrapper is that it removes the efficiency and readability benefits of using primitives.
The json comes out looking like:
{"type":"MapContainer","map":[{"type":"SubA","data":1.0},{"type":"StringWrapper","s":"valueA"},{"type":"SubB","data":2.0},{"type":"DoubleWrapper","d":2.0},{"type":"SubB","data":3.0},{"type":"SubA","data":1.0},{"type":"SubB","data":4.0},{"type":"matt.play.FakeNull"}]}
I don't like the way this looks. I want the nulls to simply be null and the primitives to simply be primitives.
import kotlinx.serialization.KSerializer
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass
import kotlin.collections.set
#Serializable
abstract class SuperClass
#Serializable
#SerialName("SubA")
data class SubA(val data: Double): SuperClass()
#Serializable
#SerialName("SubB")
data class SubB(val data: Double): SuperClass()
#Serializable
#SerialName("MapContainer")
data class MapContainer<K: SuperClass, V>(val map: Map<K, V>): Map<K, V> by map
#Serializable
#SerialName("StringWrapper")
data class StringWrapper(val s: String)
#Serializable
#SerialName("DoubleWrapper")
data class DoubleWrapper(val d: Double)
object StringClassSerializer: KSerializer<String> {
override val descriptor = buildClassSerialDescriptor("string")
override fun deserialize(decoder: Decoder) = decoder.decodeSerializableValue(StringWrapper.serializer()).s
override fun serialize(encoder: Encoder, value: String) =
encoder.encodeSerializableValue(StringWrapper.serializer(), StringWrapper(value))
}
object DoubleClassSerializer: KSerializer<Double> {
override val descriptor = buildClassSerialDescriptor("double")
override fun deserialize(decoder: Decoder) = decoder.decodeSerializableValue(DoubleWrapper.serializer()).d
override fun serialize(encoder: Encoder, value: Double) =
encoder.encodeSerializableValue(DoubleWrapper.serializer(), DoubleWrapper(value))
}
#Serializable
object FakeNull
fun main() {
val theMap = mutableMapOf<SuperClass, Any?>()
theMap[SubA(1.0)] = "valueA"
theMap[SubB(2.0)] = 2.0
theMap[SubB(3.0)] = SubA(1.0)
theMap[SubB(4.0)] = FakeNull /*wish I could make this just `null`*/
val theMapContainer = MapContainer(theMap)
val format = Json {
allowStructuredMapKeys = true
ignoreUnknownKeys = true
serializersModule = SerializersModule {
polymorphic(SuperClass::class) {
subclass(SubA::class)
subclass(SubB::class)
}
polymorphic(Any::class) {
/*I wish I could remove all of this primitive wrapper stuff*/
default {
when (it) {
StringWrapper::class.simpleName -> StringClassSerializer
DoubleWrapper::class.simpleName -> DoubleClassSerializer
else -> throw RuntimeException("unknown type: ${it}?")
}
}
subclass(String::class, StringClassSerializer)
subclass(Double::class, DoubleClassSerializer)
subclass(SubA::class)
subclass(SubB::class)
subclass(FakeNull::class)
}
polymorphic(
MapContainer::class, MapContainer::class, actualSerializer = MapContainer.serializer(
PolymorphicSerializer(SuperClass::class),
PolymorphicSerializer(Any::class)
) as KSerializer<MapContainer<*, *>>
)
}
}
val encoded = format.encodeToString(PolymorphicSerializer(MapContainer::class), theMapContainer)
println("\n\n${encoded}\n\n")
val decoded = format.decodeFromString(PolymorphicSerializer(MapContainer::class), encoded)
if (theMapContainer != decoded) {
throw RuntimeException("the decoded object is not the same as the original")
} else {
println("success")
}
}
Primitives (such as strings, numbers, and enums) by default are serialized as JSON primitives (e.g., "answer" or 42), not JSON objects ({ ... }). This is why they don't support polymorphic serialization; there is no "space" to place the type information in (the class discriminator).
There is no JSON object to place the class discriminator in, e.g., {"type": "fully.qualified.Name"} by default.
But, kotlinx serialization does allow you to write custom serializers, which allows you to work around this. I wrote a custom serializer for enums since I wanted to register enums as concrete types in polymophic serialization. It sounds like you should be able to do something similar. (Disclosure: I only read your problem description in detail; not your ongoing attempts/solution.)
A serializer which supports registering [Enum]s as subclasses in polymorphic serialization when class discriminators are used.
When class discriminators are used, an enum is not encoded as a structure which the class discriminator can be added to.
An exception is thrown when initializing [Json]: " "Serializer for of kind ENUM cannot be serialized polymorphically with class discriminator."
This serializer encodes the enum as a structure with a single value holding the enum value.
Use this serializer to register the enum in the serializers module, e.g.:
subclass( <enum>::class, PolymorphicEnumSerializer( <enum>.serializer() )
This custom serializer can possibly be generalized to any primitive type and thus support your use case.

Does Kotlin Support Member Sealed Overrides?

In Kotlin we can modify a class with the sealed modifier to denote that the class can only be extended within the same module; or from the docs:
Sealed classes and interfaces represent restricted class hierarchies that provide more control over inheritance. All subclasses of a sealed class are known at compile time. No other subclasses may appear after a module with the sealed class is compiled. For example, third-party clients can't extend your sealed class in their code. Thus, each instance of a sealed class has a type from a limited set that is known when this class is compiled.
What I want to know is, can the same or similar behaviour be applied to class members; for example, consider the following code. All of the classes and interfaces exist in the same module:
// I don't want to seal this because it should be implementable beyond this module.
interface Hashable {
val hash: Hash
}
// I don't want to seal this because it should be extensible beyond this module.
abstract class Base : Hashable {
final override val hash: Hash get() = hashOf(...)
}
open class Derived : Base {
// This doesn't work because it's final in the base class.
final override val hash: Hash get() = hashOf(...)
}
What I essentially want to express is, "I (the developer) determine how a Base should create it's hash, until I (the developer) state otherwise in a derived class. Nobody else outside of this module has the ability to alter how each extension or derivative of Base may create its hash."
Is this possible?
You can create additional property with internal visibility:
abstract class Base : Hashable {
final override val hash: Hash get() = _hash
internal open val _hash: Hash get() = hashOf(...)
}
open class Derived : Base() {
override val _hash: Hash get() = hashOf(...)
}

Best way of handling multiple object instances

Due in part to the fact that I cannot create data classes without parameters in Kotlin, I use objects for those cases, e.g.
sealed class Node {
object Leaf : Node()
data class Branch(val left:Node, val right:Node) : Node()
}
The issue is that sometimes, I end up with multiple instances of the Leaf class. Obviously this should not generally happen, but it occurs when serializing and deserializing with some frameworks and with some test cases.
Now, you might argue that I should fix those cases, but it's hard to know where they might be, and not always possible or desirable to modify the deserialization semantics of frameworks.
As such, I want all instances of my objects to act as the same value, much like a parameter-less data class would (or a parameterless case class in Scala).
My best solution so far is the following, included in every object I create that might encounter this issue:
object SaneLeaf {
override fun hashCode() = javaClass.hashCode()
override fun equals(other: Any?) = other?.javaClass == javaClass
}
Obviously, this is verbose and error prone, since it doesn't seem possible to abstract away those implementations to an interface. A super-class would work in cases where the object doesn't need to extend another class, but that's often not the case.
Alternatively, I can create a data class with a Nothing parameter. But that seems like even more of a hack.
How have others dealt with this issue? Are there plans to add hashCode and equals implementations to objects that follow the presumed semantics of those classes (all instances should be equal / same hashCode)?
I believe having multiple instances of an object's underlying class is really an issue you should fix, but there's a simpler workaround that allows you to have the equality semantics you described.
You can define an abstract class that performs the equality logic and make the sealed class inherit from it, like this:
abstract class SingletonEquality {
override fun equals(other: Any?): Boolean =
this::class.objectInstance != null && other?.javaClass == this.javaClass ||
super.equals(other)
override fun hashCode(): Int =
if (this::class.objectInstance != null)
javaClass.hashCode() else
super.hashCode()
}
And the usage:
sealed class Node : SingletonEquality() {
object Leaf : Node()
data class Branch(val left:Node, val right:Node) : Node()
}
Here, Leaf will inherit the equals implementation from SingletonEquality and get compared just the way you want.

Kotlin: why use Abstract classes (vs. interfaces)?

I'm aware of two differences between Abstract classes and Interfaces in Kotlin:
An abstract class can have state (e.g. var...)
A class can implement multiple interfaces, but not multiple abstract classes.
Since Kotlin is a rather fresh language, I wonder why Abstract Classes were not abandoned? Interfaces seem superior tool, with a very little need for Abstract Classes.
To elaborate: Kotlin does support concrete function implementation in interfaces, e.g.:
interface Shiny {
fun shine(amount : Int) // abstract function
fun reflect(s : String) { print ("**$s**") } // concrete function
}
Can someone provide a strong practical example of the need for Abstract Classes?
The practical side of abstract classes is that you can encapsulate a part of implementation that works with the state, so that it cannot be overridden in the derived classes.
In an interface, you can only define a property without a backing field, and an implementation class must override that property (with either a backing field or custom accessors).
Given that, you cannot define logic that stores some state in an interface in a reliable way: an implementation class might override the properties in an unexpected way.
Example:
interface MyContainer {
var size: Int
fun add(item: MyItem) {
// ...
size = size + 1
}
}
Here, we provide a default implementation for add that increments size. But it might break if an implementing class is defined like this:
class MyContainerImpl : MyContainer {
override val size: Int
get() = 0
set(value) { println("Just ignoring the $value") }
}
On contrary, abstract classes support this use case and thus allow you to provide some guarantees and contract for all their implementations: they can define some state and its transitions that will stay the same in a derived class.
Apart from that, abstract classes can have non-public API (internal, protected) and final members, whereas interfaces cannot (they can only have private members, which can be used in the default implementations), and all their default implementations can be overridden in the classes.
Abstract classes exist essentially for a hierarchy of classes. For example, if the abstract parent class had a concrete function that was also defined in the child class which extends the parent class, then in certain cases it would be necessary to call the parent's function. When you use an interface it is impossible to do so due to the entirely abstract nature of the class.

What is the rationale behind having companion objects in Scala?

Is there a case where a companion object (singleton) for a class is needed? Why would I want to create a class, say Foo and also create a companion object for it?
The companion object basically provides a place where one can put "static-like" methods. Furthermore, a companion object, or companion module, has full access to the class members, including private ones.
Companion objects are great for encapsulating things like factory methods. Instead of having to have, for example, Foo and FooFactory everywhere, you can have a class with a companion object take on the factory responsibilities.
Companion objects are useful for storing state and methods that are common to all instances of a class but they do not use static methods or fields. They use regular virtual methods which can be overridden through inheritance. Scala truly has nothing static. There are lots of ways you can use this but here's a simple example.
abstract class AnimalCounter
{
var animals = 0
def name: String
def count()
{
animals += 1
println("%d %ss created so far".format(animals, name))
}
}
abstract class Animal
{
def companion: AnimalCounter
companion.count()
}
object Dog extends AnimalCounter
{
val name = "dog"
}
class Dog extends Animal
{
def companion = Dog
}
object Cat extends AnimalCounter
{
val name = "cat"
}
class Cat extends Animal
{
def companion = Cat
}
Which produces this output:
scala> new Dog
1 dogs created so far
scala> new Cat
1 cats created so far
scala> new Dog
2 dogs created so far
scala> new Cat
2 cats created so far
...and it's a good place to store static factory methods (not that DP) for accompanied classes. If you name those overloaded factory methods apply(/.../) you will be able to create/initialize you class
without 'new' (not really that important)
with different possible sets of parameters (compare to what Bloch writes in Effective Java about telescoping constructor)
with the ability to to decide which derived class you want to create instead of the abstract (accompanied) one
Example code:
abstract class AbstractClass;
class RealThing(s: String) extends AbstractClass;
class AlternativeThing(i: Int) extends AbstractClass;
object AbstractClass {
def apply(s: String) = {
new RealThing(s)
}
def apply(i: Int) = {
new AlternativeThing(i)
}
}
// somewhere else you can
val vs = AbstractClass("asdf") // gives you the RealThing wrapped over string
val vi = AbstractClass(123) // gives you AlternativeThing wrapped over int
I wouldn't call the object/base class AbstractXxxxx because it doesn't looks bad: like creating something abstract. Give those names a real meaning.
Consider using immutable, method less, case classes and seal the abstract base class.
In addition to the things Saem said in his reply, the Scala compiler also looks for implicit conversions of types in the corresponding companion objects (of either the source or the target), so the conversions don't need to be imported.
About the reason for singleton objects in general Programming in Scala says:
As mentioned in Chapter 1, one way in which Scala is more object-oriented than Java is that classes in Scala cannot have static members. Instead, Scala has singleton objects (p. 65).
I always see companion objects as a bridge to write both functional and object oriented code in Scala. Many times we just need pure functions which take some input and provide a processing result. Putting those relevant functions in the companion object makes it easy to look up and use, for myself as well as some one building on top of my code.
Moreover, it is a language provided feature to write the singleton pattern without doing anything. This is especially useful when you need a singleton to encapsulate a delegator for the life of JVM. For example, writing a simple HTTP client library in Scala where you can encapsulate an underlying Java implementation based delegator and let consumers of your API live in pure world.
If you define class and object in same file with same name, they known as companion class and object. Scala don't have static as JAVA keyword, You can take as replacement of static with companion class and object in Scala.
For more detail information please check article
class and object keyword in scala programming
At first, it provides a clear separation of static vs non static methods methods.Also provide a simple way to create singleton class.
It also can inherit methods from other classes and/or traits, which cannot be done with Java static methods.and can be passed as a parameter.