In this answer, Michael suggests that the generic type parameter be made co-variant in order to allow the creation of an empty node.
I get that the generic type parameter is in all output positions since all the properties of the Tree<T>
and its sub-types are read-only (val
's).
But it does have the type parameter in an input position in the constructor.
I thought that that code wouldn't work in C# so I tried it out and, to my surprise, it worked just fine.
// See this: https://stackoverflow.com/questions/36753579/algebraic-data-types-in-kotlin
// Short url: https://stackoverflow.com/a/36753782/303685
interface ITree<out T> { }
class Tree<T>: ITree<T> { }
sealed class Node<T> : Tree<T>
{
private readonly T _left;
private readonly T _right;
public Node(T left, T right)
{
_left = left;
_right = right;
}
public T Left { get { return _left; } }
public T Right { get { return _right; } }
}
class Program
{
static void CovarianceTest1()
{
ITree<object> tree = new Node<string>("Hello", "World!");
}
}
I realize now that in doing this exercise, I learnt something new about variance.
So, my first question is:
Are co-variant type parameters allowed in input positions in constructors? In what other places are type parameters allowed to disregard their variance qualifiers?
Another thing I learnt about variance is that the variant generic type parameter may not even appear in the variant interface declaration as seen in the example below.
interface ITree<out T> { }
You'll see that the ITree<out T>
interface does not have T
in either input or output positions. This also came as a shock to me.
My second question is:
And the other question I have is, what is the C# equivalent of the Nothing
type in Kotlin? The answer says that Nothing
is the most sub-type that cannot further be derived. It is the exact opposite of Any
(or the most base type in other languages).
To emulate that code in C#, it didn't make sense to have this:
class Empty : Tree<null> { }
Because that's just illegal C# code and null
also doesn't seem analogous to Nothing
.
So, I had to fake a dummy like so to imitate the Empty
class declaration.
sealed class Dummy { }
sealed class Empty : Tree<Dummy>
{
private static Empty _empty = null;
private static object syncLock = new object();
private Empty() { }
public Empty Instance
{
get
{
if (_empty == null)
{
lock (syncLock)
{
if (_empty == null)
{
_empty = new Empty();
}
}
}
return _empty;
}
}
}
My third and final question is:
Therefore, my final question is, is there a place that contains an exhaustive list of all the types available in Kotlin along with their descriptions? Because even though the Basic Types page lists most of the common ones, it seems not to be an exhaustive list. The types not listed there are all sprinkled over the documentation. Like in the instance above, they just appear with a mention on a page here or there.