Let's say I want to declare a simple algebraic data type for entire lists:
sealed class IntList data class Cons(val head: Int, val tail: IntList): IntList() data class Nil() : IntList()
However, the last announcement results in an error
A data class must have at least one primary constructor parameter
- Why is this limitation present? If you look at the documentation, there are apparently no good technical reasons for requiring the data class constructors to be non-null.
Is it possible to express constructors with a zero value without the need to write many patterns? If I change the last ad to something like
sealed class Nil() : IntList()
then I lose the free hashCode() and equals() implementations that become free with data class declarations.
EDIT
Alex Filatov gave a short short decision below. Obviously, you don't need more than one instance of Nil , so we can just define a singleton object
object Nil : IntList()
However, what would we do if our lists were parameterized by a type parameter? That is, now the first two lines of our definition will be
sealed class List<A> data class Cons<A>(val head: A, val tail: List<A>): List<A>()
We cannot declare a polymorphic singleton Nil object, which is obtained from List<A> for any A , since we must provide a specific type for A at the time of declaration. The solution (taken from this post ) is to declare A as a parameter of the covariant type and declare Nil as a subtype of List<Nothing> as follows:
sealed class List<out A> data class Cons<A>(val head: A, val tail: List<A>): List<A>() object Nil : List<Nothing>()
It allows us to write
val xs: List<Int> = Cons(1, Cons(2, Nil)) val ys: List<Char> = Cons('a', Cons('b', Nil))
kotlin
Ulrik Rasmussen
source share