Error al usar un object para implementar una list vacía

Estoy tratando de reescribir la interfaz de la Lista como un ejercicio para aprender la Progtwigción Funcional en Kotlin, pero no puedo entender por qué me sale un error cuando bash tener un object como la list vacía, que no ocurre en la biblioteca estándar de Kotlin. En mi código, ver a continuación, quiero usar NIL como una list vacía singleton, usando list () como la function para devolverlo. Sin embargo, esto genera un error de desajuste de tipo en la function de tipo "Lista requerida. Encontrado NIL".

interface List<A> { val empty: Boolean val head: A val tail: List<A> fun cons(a: A): List<A> = Cons(a, this) } object NIL : List<Nothing> { override val empty: Boolean = true override val head: Nothing get() = throw IllegalStateException("head called on empty list") override val tail: List<Nothing> get() = throw IllegalStateException("tail called on empty list") } private class Cons<A>(override val head: A, override val tail: List<A>) : List<A> { override val empty: Boolean = false } fun <A> list(): List<A> = NIL // Type mismatch. Requinetworking: List<A>. Found: NIL fun <A> list(vararg a: A): List<A> { var n = list<A>() for (e in a.reversed()) { n = Cons(e, n) } return n } 

En la biblioteca estándar, este error no ocurre, como puede ver en EmptyList en Collections.kt . ¿Estoy haciendo algo mal o me faltan algunos conceptos que hacen que este último sea posible y el anterior no?

Evaluación de soluciones propuestas

De las tres soluciones propuestas, la única que permite pasar el código de testing a continuación es la que usa el object anónimo , mientras que las otras arrojan la exception java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Void .

 assertEquals("a", list<String>().cons("a").head) 

Sin embargo, si cambio NIL a NIL : List<Any?> , La solución NIL as List<A> funciona sin ningún problema.

puede convertir una List<Nothing> en una List<A> explícita por una palabra key, por ejemplo:

 fun <A> list(): List<A> = NIL as List<A>; 

SI desea suprimir las advertencias del comstackdor, puede anotar la function con la anotación @Suppress , por ejemplo:

 @Suppress("UNCHECKED_CAST") fun <A> list(): List<A> = NIL as List<A>; 

O si no te gusta de esta manera, puedes usar un object anónimo en una function, por ejemplo:

 fun <A> list(): List<A> = object : List<A> { override val empty: Boolean = true override val head: A get() = throw IllegalStateException("head called on empty list") override val tail: List<A> get() = throw IllegalStateException("tail called on empty list") }; 

Generic en su interfaz debe ser <out A> lugar de <A> .

Además, IntelliJ Idea muestra una advertencia cuando utiliza generics sin variación en esos casos.

  • Android 2 Retrofit llamada sincrónica
  • Vert.x. ¿Cómo crear una aplicación de JVM políglota real?
  • ¿Kotlin es "paso por valor" o "paso por reference"?
  • Cómo deserializar las classs de datos henetworkingados de Kotlin con Gson
  • Cómo usar anko spinner?
  • Sugar ORM, ¿Listar todo en Kotlin? Java funciona, pero Kotlin no
  • Obteniendo el error "Tipos incompatibles" cuando se usa el código generado a partir de una class de datos Kotlin
  • ¿Cuál es la syntax para Class <? extiende class_name> en kotlin?
  • ¿Cómo obtengo el valor de una propiedad con reflection?
  • ¿Debo usar @Repository cuando solo uso JdbcTemplate en mi class DAO?
  • Kotlin: ambigüedad de resolución de sobrecarga en Eclipse, pero no en IntelliJ