Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algebraic data types in Kotlin

I am trying to figure out how to use algebraic data types in Kotlin, so I'm trying to implement a basic BinaryTree type the following way.

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>()
}

This is all fine, and lets me construct the following tree:

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

However I would like to have an "Empty" type as well, so I can express the following:

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

I tried the following:

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()
}

Though I get the error that Type argument is expected at object Empty: Tree(), which is actually quite logical.

I tried

object Empty: Tree<T>()

But it resulted in "Unresolved reference: T". As a last resort, I tried writing

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

But the compiler says "Type parameters are not allowed for objects"

Is there a way to express this in Kotlin? Empty should be a singleton, this is why it should be an object. By making it a class, it solves the compiler problems, but then I have to put parentheses after it like that => Empty(). Also, it creates unnecessary objects, while it really should be a singleton value.

I'd appreciate any help on this issue. :)

like image 900
pjozsef Avatar asked Apr 20 '16 19:04

pjozsef


People also ask

Does kotlin have sum types?

In Kotlin, Sum Types are supported through inheritance, using sealed classesand data classes which inherit from said sealed class. It looks like a bit of a hack, and perhaps it is. It seems like it wasn't built into the language and it was more of a discovered feature than a planned feature.

What is an algebraic data type Haskell?

This is a type where we specify the shape of each of the elements. Wikipedia has a thorough discussion. "Algebraic" refers to the property that an Algebraic Data Type is created by "algebraic" operations. The "algebra" here is "sums" and "products": "sum" is alternation ( A | B , meaning A or B but not both)

What is a sealed class Kotlin?

A sealed class defines a set of subclasses within it. It is used when it is known in advance that a type will conform to one of the subclass types. Sealed classes ensure type safety by restricting the types to be matched at compile-time rather than at runtime.


1 Answers

First you need to make T an out parameter. Then you can use Nothing as a type argument for 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 is a special type in Kotlin, which cannot have an instance and is a subtype of all other types. So I would say it's opposite to Any in Kotlin type hierarchy.

like image 142
Michael Avatar answered Sep 20 '22 06:09

Michael