// Leaf of T value
// Node of Tree<T> left * Tree<T> right
public sealed class Tree<T>
{
// the space wasted here is why - in managed languages with deterministic GCs like C# and Java
// sub class based implementations are likely better in perf
// You can't actually make C++ style union types - but still they can be very useful in some areas
private readonly bool _isLeaf;
private readonly T _value;
private readonly Tree<T> _left;
private readonly Tree<T> _right;
// assume constructors for each, likely static Make methods and the like that guarantee
// the invariants
public explicit extension Leaf for Tree<T> Person
{
public T Value => this._value;
}
public explicit extension Node for Tree<T> Person
{
public Tree<T> Left => this._left;
public Tree<T> Right => this._right;
}
public TResult Apply(Func<Leaf, TResult> onLeaf, Func<Node, TResult> onNode)
{
return _isLeaf ? onLeaf(((Leaf)this)) : onNode(((Node)this))?
}
// But actually more useful is hiding things entirely anyway, which doesn't need extension types,
// I include it here to demonstrate
public TResult Fold(Func<T,TResult> onLeaf, Func<TResult,TResult,TResult> combine)
{
// You could make this out of Apply.
// But it would be (without nuts amount of compiler work) very slow
// and an absolute bitch to debug
// This would also blow the stack - you'd write it non recursively
if (_isLeaf)
{
return onLeaf(_value);
}
return combine(_left.Fold(onLeaf, combine), _right.Fold(onLeaf, combine))?
}