X<Y<Child>> is not a subtype of X<Y<? extends Parent>>. We have to go wildcard all the way - X<? extends Y<? extends Parent>>.
The subtyping rules don't care about final-ness of types. For example, X<String> is a distinct type from X<? extends String>, even though String has only one subtype (itself). Zhong Yu On Sun, Jul 14, 2013 at 8:04 AM, Jed Wesley-Smith <j...@wesleysmith.io> wrote: > (accidentally didn't post to the list) > >> You probably know that the example provided is not completed ported to > work with our Optional implementation, > > It should be, for the example I wrote an Optional that is final and should > be otherwise identical. It should certainly be fairly easy for any > committer to try. If you can make it work without the ? extends Optional > I'd love an explanation of how. > >> and fugue works around the type system with Option as abstract class. > > As I've tried to explain, this isn't about the implementation of the > container class, but how covariance works with a parameterised class. > > We originally had the non-, but in a discussion with Brian he alerted us to > the fact that the signature was wrong. We hastily fixed it: > > https://bitbucket.org/atlassian/fugue/commits/9eca663326a5baeb8f23974732ec585d5627a05c > > To further demonstrate, I give you a minimal example of a final Optional > implementation that does not compile for this test: > > https://gist.github.com/jedws/5993596#file-gistfile1-java-L57 > > cheers, > jed. > > > > On 14 July 2013 15:02, Henry Jen <henry....@oracle.com> wrote: > >> I think I understand what you are saying. However, unless we make >> Optional not final, the extends part just doesn't matter. >> >> You probably know that the example provided is not completed ported to >> work with our Optional implementation, and fugue works around the type >> system with Option as abstract class. >> >> Cheers, >> Henry >> >> On Jul 13, 2013, at 4:35 PM, Jed Wesley-Smith >> <j...@wesleysmith.io><j...@wesleysmith.io>wrote: >> >> I did supply a test that you can use to try it. >> >> What we are talking about is whether type Box<Parent> is substitutable >> by Box<Child> in the contravariant position. Intuitively we think we only >> need Box<? extends Parent> because we only care about the type parameter, >> but the type – as you point out – is actually different. Box<Parent> is not >> "inherited by" Box<Child>. >> >> Specifically, if we have a consuming Box, and we replace it with a Box >> of a more specific type parameter, we could attempt feed the more general >> type into it, ie. a Box<Child> isn't going to appreciate having Parent fed >> to it. This is why covariance and mutable containers don't mix well, and >> why Java's covariant arrays are problematic. >> >> In this situation we have an immutable container, and we can substitute >> the type of our container with one of a more specific type, as it will only >> ever supply a value – and a value of Child will suffice as a Parent. So, >> for this case we need a Box that is substitutable, and therefore we need to >> add the covariance to our box. >> >> <? extends Box> is simply adding covariance to our Box type. >> >> For a much better explanation than I can give about this, see this >> excellent post describing generics in Scala, which – apart from have >> declaration-site variance and using [A] in place of <A> – generally follow >> the same pattern: >> >> >> http://termsandtruthconditions.herokuapp.com/blog/2012/12/29/covariance-and-contravariance-in-scala/ >> >> cheers, >> jed. >> >> >> On 14 July 2013 04:49, Henry Jen <henry....@oracle.com> wrote: >> >>> I think the type you talking about here is Optional<? extends U> instead >>> of ? extends Optional<U>. >>> >>> IIRC, Optional<? extends U> is not a subtype of Optional<U>, just like >>> any other Collection class. List<Child> is not a List<Parent>. >>> >>> Cheers, >>> Henry >>> >>> >>> On Jul 13, 2013, at 3:15 AM, Jed Wesley-Smith <j...@wesleysmith.io> >>> wrote: >>> >>> > The ? extends Optional is unnecessary in flatMap as Optional is final. >>> >>> interestingly enough, it actually is. >>> >>> try the following test: >>> >>> class OptionalTest { >>> class Parent {}; >>> >>> class Child extends Parent {}; >>> >>> @Test public void covariantReturn() { >>> Optional<Parent> some = some(new Parent()); >>> Function<Parent, Optional<Child>> f = new Function<Parent, >>> Optional<Child>>() { >>> @Override public Optional<Child> apply(Parent p) { >>> return some(new Child()); >>> } >>> }; >>> Optional<Parent> mapped = some.<Parent> flatMap(f); >>> assertThat(mapped.get(), notNullValue()); >>> } >>> } >>> >>> adapted from the fugue test suite: >>> >>> >>> https://bitbucket.org/atlassian/fugue/src/96a65067fb7aaf1edae1bffa07167a5865cbebec/src/test/java/com/atlassian/fugue/OptionTest.java#cl-155 >>> >>> The point to remember is that Optional<Child> is a type and as such is >>> actually a subtype of Optional<Parent> – and therefore requires a >>> covariant return. >>> >>> cheers, >>> jed. >>> >>> >>> >>> >>> On 13 July 2013 04:15, Mike Duigou <mike.dui...@oracle.com> wrote: >>> >>>> The ? extends Optional is unnecessary in flatMap as Optional is final. >>>> Otherwise this looks good. >>>> >>>> Mike >>>> >>>> On Jul 5 2013, at 14:37 , Henry Jen wrote: >>>> >>>> > Hi, >>>> > >>>> > Please review the webrev at >>>> > >>>> > http://cr.openjdk.java.net/~henryjen/ccc/8015317.0/webrev/ >>>> > >>>> > Which adds following method to Optional, >>>> > >>>> > public static <T> Optional<T> ofNullable(T value) {} >>>> > public Optional<T> filter(Predicate<? super T> predicate) {} >>>> > public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {} >>>> > public<U> Optional<U> flatMap(Function<? super T, ? extends >>>> Optional<U>> >>>> > mapper) {} >>>> > >>>> > Also included is some cleanup on javadoc. >>>> > >>>> > Cheers, >>>> > Henry >>>> >>>> >>>> >>> >>> >> >> >