Алгебраические типы данных в Котлине

Я пытаюсь выяснить, как использовать алгебраические типы данных в Kotlin, поэтому я пытаюсь реализовать базовый тип BinaryTree следующим образом.

sealed class Tree<T>{
  class Node<T>(val left: Tree<T>, val right: Tree<T>): Tree<T>()
  class Leaf<T>(val value: T): Tree<T>()
}

Все это прекрасно, и позволяет мне построить следующее дерево:

val myTree1: Tree<Int> = Node(Leaf(4), Leaf(2))

Однако я хотел бы также иметь "пустой" тип, поэтому я могу выразить следующее:

val myTree1: Tree<Int> = Node(Node(Leaf(4), Leaf(3)), Empty)

Я попробовал следующее:

sealed class Tree<T>{
  class Node<T>(val left: Tree<T>, val right: Tree<T>): Tree<T>()
  class Leaf<T>(val value: T): Tree<T>()
  object Empty: Tree()
}

Хотя я получаю ошибку, что аргумент типа ожидается на объекте Empty: Tree(), что на самом деле довольно логично.

Я пробовал

object Empty: Tree<T>()

Но это привело к "неразрешенной ссылке: T". В крайнем случае я попытался написать

object Empty<T>: Tree<T>()

Но компилятор говорит: "Параметры типа не разрешены для объектов"

Есть ли способ выразить это в Котлине? Пустой должен быть синглтон, поэтому он должен быть объектом. Сделав его классом, он решает проблемы с компилятором, но после этого мне нужно поставить круглые скобки после этого = > Empty(). Кроме того, он создает ненужные объекты, в то время как это действительно должно быть одно значение.

Буду признателен за любую помощь по этой проблеме.:)

Ответ 1

Сначала вам нужно сделать параметр T a out. Затем вы можете использовать Nothing как аргумент типа для Empty.

sealed class Tree<out T>{
  class Node<T>(val left: Tree<T>, val right: Tree<T>): Tree<T>()
  class Leaf<T>(val value: T): Tree<T>()
  object Empty: Tree<Nothing>()
}

Nothing - особый тип в Котлине, который не может иметь экземпляр и является подтипом всех других типов. Поэтому я бы сказал, что это противоположно Any в иерархии типов Котлин.