2

I want to convert a List<Promise<Boolean>> into a Promise<List<Boolean>>. I know that this can be achieved using the sequence method, but I'm having some problems getting the types right.

Here is what I've tried:

First (naive) approach

List<Promise<Boolean>> foo = new ArrayList<Promise<Boolean>>;

// ... Code that loops over some other collection
// and adds multiple Promise<Boolean>s to foo

Promise<List<Boolean>> bar = Promise.sequence(foo);

This does not compile because "the argument type List<Promise<Boolean>> does not conform to formal parameter type Iterable<Promise<? extends A>>".

Second approach

Declaring the type of foo to conform to the formal parameter type as suggested by the error message above:

List<Promise<? extends Boolean>> foo = new ArrayList<Promise<Boolean>>()

As per the sub-typing rules laid out in this answer, Promise<Boolean> should be a subtype of Promise<? extends Boolean>, but I am getting a type mismatch here: "cannot convert from ArrayList<F.Promise<Boolean>> to List<F.Promise<? extends Boolean>>.

Third approach

Removing type information from instantiation of ArrayList<Promise<Boolean>>:

List<Promise<? extends Boolean>> foo = new ArrayList();

This compiles but results in a warning about unchecked conversion that I would like to get rid of: "The expression of type ArrayList needs unchecked conversion to conform to List<F.Promise<? extends Boolean>>."


What am I missing? How can I get the types to line up correctly?

Community
  • 1
  • 1
itsjeyd
  • 5,070
  • 2
  • 30
  • 49

1 Answers1

2

You can use this declaration instead:

List<Promise<? extends Boolean>> foo = new ArrayList<Promise<? extends Boolean>>();

Check the following answers to understand why this works:

Community
  • 1
  • 1
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • Thanks for your answer! This works, but only in that it removes any warnings/compilation issues for the line where I am declaring `foo`. Unfortunately, though, it prevents me from adding any `Promise`s to `foo` before calling `sequence` on it: "The method `add` in type `List` is not applicable for the arguments `F.Promise`. – itsjeyd Jan 10 '14 at 09:52
  • Ok, then what you can do is, fill up your list first, and then after that assign it to the `foo` reference with the above type, and then pass it to `sequence()` method. That's because you cannot add anything to `List extends SomeType>` kind of lists. – Rohit Jain Jan 10 '14 at 09:55
  • And what should that temporary list be declared as? Because when I do `List> temp = new ArrayList>();`, I can `add` to `temp` just fine but after assigning `temp` to `foo` via `foo = temp;`, passing `foo` to `sequence()` won't work. The error message is basically the same as the one I got for my first approach. – itsjeyd Jan 10 '14 at 10:06
  • @itsjeyd Is your foo of type `List extends Promise extends Boolean>> foo`? – Rohit Jain Jan 10 '14 at 10:07
  • @itsjeyd Ah! A minor mistake. I've updated the answer. Actually, you don't need to create a `temp` list. Just the above one would work. – Rohit Jain Jan 10 '14 at 10:10
  • ... because `ArrayList>` trivially extends `List>`. Of course. :) Case closed, thanks. – itsjeyd Jan 10 '14 at 10:15