{"action":"created","issue":{"url":"https://api.github.com/repos/ceylon/ceylon-spec/issues/1401","labels_url":"https://api.github.com/repos/ceylon/ceylon-spec/issues/1401/labels{/name}","comments_url":"https://api.github.com/repos/ceylon/ceylon-spec/issues/1401/comments","events_url":"https://api.github.com/repos/ceylon/ceylon-spec/issues/1401/events","html_url":"https://github.com/ceylon/ceylon-spec/issues/1401","id":101428953,"number":1401,"title":"Contravariance, missing specification ?","user":{"login":"vbeauPer","id":13481767,"avatar_url":"https://avatars.githubusercontent.com/u/13481767?v=3","gravatar_id":"","url":"https://api.github.com/users/vbeauPer","html_url":"https://github.com/vbeauPer","followers_url":"https://api.github.com/users/vbeauPer/followers","following_url":"https://api.github.com/users/vbeauPer/following{/other_user}","gists_url":"https://api.github.com/users/vbeauPer/gists{/gist_id}","starred_url":"https://api.github.com/users/vbeauPer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vbeauPer/subscriptions","organizations_url":"https://api.github.com/users/vbeauPer/orgs","repos_url":"https://api.github.com/users/vbeauPer/repos","events_url":"https://api.github.com/users/vbeauPer/events{/privacy}","received_events_url":"https://api.github.com/users/vbeauPer/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":78,"created_at":"2015-08-17T14:10:19Z","updated_at":"2015-09-01T19:11:28Z","closed_at":null,"body":"Hi, working on covariance and contravariance, I found a proof that if X and Y are disjoint you can still have `Consumer<X&Y>` different from `Consumer<Nothing>`.\r\nIn this proof you should keep in mind that `X&Y` could be Nothing only in covariance (or X or Y is Nothing).\r\n\r\n*This part with covariance is only to do a parallel comparison*\r\nWith `Producer<out E>`, we have `Producer<X> | Producer<Y>` is subtype of `Producer<X|Y>`, to work properly we need the entire content of `Producer<X|Y>`.\r\nif producer have a function `E getSomeElement()`, `Producer<X|Y>` contains all of :\r\n1. Producers which returns E as X (`Producer<X>` this includes `Producer<Nothing>`), \r\n2. Producers which returns E as Y (`Producer<Y>`) as described in `Producer<X> | Producer<Y>`,\r\n3. and Producers which returns E as `X|Y` (or an union of covariant subtype of X and Y).\r\n\r\nThe same in contravariant we have, with `Consumer<in E>`, `Consumer<X> | Consumer<Y>` is subtype of `Consumer<X&Y>`, again we need full content of `Consumer<X&Y>`.\r\nif consumer have a function `void consume(E element)`, `Consumer<X&Y>` contains all of :\r\n1. Consumers which accepts parameter E as X (`Consumer<X>` so could be `Consumer<Anything>`),\r\n2. Consumers which accepts parameter E as Y (`Consumer<Y>`) as described in `Consumer<X> | Consumer<Y>`,\r\n3. and Consumers which accepts parameter E as `X&Y` (or an intersection of covariant supertype of X and Y, which they do not have in common). **This never does include all Consumer<E> types as `Consumer<Nothing>`.** Now Let's consider that `X&Y` is Nothing in covariance, at this step we could have 2 ways of thinking :\r\n  * one way is to consider that `Consumer<X&Y>` is instantiable, then this generic class comes with the same signature as `Consumer<Nothing>`, then we have this third part containing ony one element :\r\n    - this instance could be considered as an instance which could be set in all `Consumer<Z>` where Z could be considered as Nothing in covariance, and does not really accept `X&Y` as parameter but Nothing which is a supertype of X&Y. \r\n    - We could also create some `Nothing<X&Y>` type to differentiate them, but here we have to deal with hierarchical specific behaviour.\r\n  * the second way if to consider that only `Consumer<Nothing>` is instantiable, not `Consumer<X&Y>` (actually in covariant this is the case with the difference that `Producer<Nothing>` could be set naturally in `Producer<X&Y>`). Then we have this third part containing no elements.\r\n\r\n**In all case we got the deal.**\r\n\r\nIf you are sceptic about this, I could show you definition space where `X&Y` is never Nothing, and then you have the trick with this specification needs (somehow just consider it has not been implemented) :\r\n  - *(IT IS NOT A PROPOSITION)* `Float&String floatString = 5.0&\"Some String\";`\r\n\r\nWell let's see some consequences of such notation in contravariance :\r\n`Consumer<Float> | Consumer<Integer>` is equivalent to `Consumer<Float&Integer>` \r\nFor the '[Unique approach to observer/observable pattern in Ceylon](http://ceylon-lang.org/blog/2015/04/19/observable/)', we could have the following `List<Anything(Created&Updated&Deleted)>` to specialize the inner list of listener, instead of `List<Anything(Nothing)>` which does not represent what it contains.\r\nIt is not perfect as you should add every subtype of Event every time. \r\nThe best way here is to have a type filter like `List<Anything(in/out Event)>` (well I have no idea how to call or represent it), where `in/out` means super or subtype of Event.\r\n\r\nThe specification to change is here '[3.2.5. The bottom type](http://ceylon-lang.org/documentation/1.0/spec/html/typesystem.html#bottomtype)', it does not includes contravariance specification.\r\n"},"comment":{"url":"https://api.github.com/repos/ceylon/ceylon-spec/issues/comments/136830857","html_url":"https://github.com/ceylon/ceylon-spec/issues/1401#issuecomment-136830857","issue_url":"https://api.github.com/repos/ceylon/ceylon-spec/issues/1401","id":136830857,"user":{"login":"RossTate","id":1139675,"avatar_url":"https://avatars.githubusercontent.com/u/1139675?v=3","gravatar_id":"","url":"https://api.github.com/users/RossTate","html_url":"https://github.com/RossTate","followers_url":"https://api.github.com/users/RossTate/followers","following_url":"https://api.github.com/users/RossTate/following{/other_user}","gists_url":"https://api.github.com/users/RossTate/gists{/gist_id}","starred_url":"https://api.github.com/users/RossTate/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RossTate/subscriptions","organizations_url":"https://api.github.com/users/RossTate/orgs","repos_url":"https://api.github.com/users/RossTate/repos","events_url":"https://api.github.com/users/RossTate/events{/privacy}","received_events_url":"https://api.github.com/users/RossTate/received_events","type":"User","site_admin":false},"created_at":"2015-09-01T19:11:28Z","updated_at":"2015-09-01T19:11:28Z","body":"> it works perfectly well\r\n \r\nWhat works perfectly well?\r\n\r\nFrom what you have said so far, in every circumstance one of `Anything(Create)|Anything(Update)` or `Anything(Nothing)` works better than `Anything(Create&Update)`."}}