One of the types in Skila library is generic Sequence
(the counterpart of IEnumerable
interface in C#). Assuming method concat
is not supposed to create exactly the same type as the original one (as in Array
for Array
, List
for List
, and so on) but simply some Sequence
how its signature should look like?
In C# it is defined as an extension method:
public static IEnumerable<TSource> Concat<TSource>( this IEnumerable<TSource> first, IEnumerable<TSource> second )
Which is almost fine until you have to play with such code:
animals = cats.Select(it => (Animal)it).Concat(dogs);
Obviously it is an obstacle and those are not welcome in Skila — here is our signature:
interface Sequence<out T> // ~ stands for Sequence def concat<C>(seq ~C) ~C where C base T; ... end end
Unlike C#, Skila has two-way constraints — you can say some type parameter A
has to inherit from B
(A is B
), or A
has to be inherited by B
(A base B
). As for concat
it is enough to write:
animals = cats +++ dogs; // temporary syntax for concat operator
base
constraint works for type inference as well — of course noticing that Object
is base of any other type is correct, but not very productive, thus for each constraint the lowest common ancestor (LCA) is computed. Still correct and probably exactly what you would like to see:
def twist<C,D,A>(b Bool,c C,d D) A where A base C; A base D; return b ? c : d; end
When you absorb this let Skila infer Animal
type for you:
animal = twist(true,cat,dog);