Say I want to declare a simple algebraic datatype for integer lists:
sealed class IntList
data class Cons(val head: Int, val tail: IntList): IntList()
data class Nil() : IntList()
但是,最后一次声明会导致错误
Data class must have at least one primary constructor parameter
- 为什么存在这种限制?查看文档,似乎没有很好的技术理由要求数据类构造函数为非空.
-
不需要编写大量样板代码就可以表达空构造函数吗?如果我把最后的声明改成
sealed class Nil() : IntList()
then I lose the free implementations of
hashCode()
andequals()
that come for free withdata class
declarations.
EDIT
亚历克斯·费拉托夫在下面给出了一个简短的解决方案.显然,你永远不需要超过一个Nil
的实例,所以我们可以定义一个单例对象
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 would be
sealed class List<A>
data class Cons<A>(val head: A, val tail: List<A>): List<A>()
我们不能为任何A
声明从List<A>
派生的多态单例Nil
对象,因为我们必须在声明时为A
提供具体类型.解决方案(取自this post)是将A
声明为协变类型参数,并将Nil
声明为List<Nothing>
的子类型,如下所示:
sealed class List<out A>
data class Cons<A>(val head: A, val tail: List<A>): List<A>()
object Nil : List<Nothing>()
这样我们就可以写
val xs: List<Int> = Cons(1, Cons(2, Nil))
val ys: List<Char> = Cons('a', Cons('b', Nil))