On Sun, Jul 31, 2016 at 11:58 AM, Dirk Lattermann <
dl...@alqualonde.de> wrote:
> // parent is set to NodeP1 just for illustration.
> NodeP1|NodeP2 parent = NodeP1();
> NodeC1 nodeC1 = NodeC1();
>
> // following line gives compiler error
> // (where does "out" come from?)
>
> // Argument must be assignable to parameter child of add in
> // ParentNode<out NodeP2|NodeC1|NodeC2>: NodeC1 is not
> // assignable to Nothing
> parent.add(nodeC1);
So what is going on here is that in order to assign a signature to
add(), the typechecker needs to form a principal instantiation of the
type ParentNode that declares add().
Unfortunately, ParentNode is invariant in its type parameter, which
makes this a tricky case. In theory, the correct result should be this
type, with a double-bounded wildcard:
ParentNode<out NodeP2|NodeC1|NodeC2 in NodeP2|NodeC1>
However, Ceylon doesn't (currently) support double-bounded wildcards
and so what it currently does in this case (i.e. where the upper bound
and lower bound are different) is it throws away the lower bound,
privileging covariance over contravariance, and assigns the type:
ParentNode<out NodeP2|NodeC1|NodeC2>
This is the type you'll see in the IDE if you hover over the call to add().
Of course, you can fix the problem easily by declaring add() on a
contravariant supertype, like this:
abstract class Node() {}
interface Parent<in Child> {
shared void add(Child child){}
}
abstract class ParentNode<Child>()
extends Node()
satisfies List<Child>&Parent<Child>
given Child satisfies Node { ... }
Which is the exact reason we have interfaces like ListMutator in the
collections hierarchy.
> Additionally, instead of the 2nd line above, I'd like to write
>
> ```ceylon
> abstract class ParentNode<Child>() of NodeP1 | NodeP2
> satisfies List<Child>
> ```
>
> but the compiler complains with
>
> Case type must be a subtype of enumerated type for every type argument
> of the generic enumerated type: NodeP1 is not assignable to
> ParentNode<Child>
>
> What's the rationale of this?
What you've defined here is not a plain sum type, but a "generalized"
algebraic type (GADT). GADTs exhibit decidability problem and for that
reason Ceylon doesn't (yet) support them.
--
Gavin King
ga...@ceylon-lang.org
http://profiles.google.com/gavin.king
http://ceylon-lang.org
http://hibernate.org
http://seamframework.org