Reputation: 979
I'm learning about generics in Dart and can't get the following example to work. The function takes an Iterable over any kind of num (int or double) and returns its sum. How can I fix this?
N sum<N extends num, T extends Iterable<N>>(T numbers) {
return numbers.reduce((acc, n) => acc + n);
}
void main() {
print(sum([1, 2, 3]));
}
Upvotes: 0
Views: 422
Reputation: 89965
There are two problems:
sum([1, 2, 3])
infers T
from the List<int>
argument, but it does not directly constrain N
. Without a constraint, N
will be assumed to be a num
, and the call will be inferred to be sum<num, List<int>>
(since List<int>
is considered to be a subtype of List<num>
). You don't need so many type parameters and instead should use:
N sum<N extends num>(Iterable<N> numbers)
acc
and n
are both of type N
, so acc + n
uses N.operator +
. Since N
derives from num
, N.operator +
must conform to num.operator +
, which is statically known to return a num
. However, the compiler cannot deduce that the returned num
must necessarily be an N
since that would be a potentially unsafe downcast.
In practice, the only types allowed to derive from num
are int
and double
, and each provides an override of operator +
that returns its own type. Therefore explicitly downcasting the result of N.operator +
should be safe, and you can fix the static type error by using:
return numbers.reduce((acc, n) => (acc + n) as N);
Upvotes: 2
Reputation: 1497
You have two options here:
//you have to specify types when calling this function(see example)
N sum<N extends num, T extends Iterable<N>>(T numbers) {
return numbers.reduce((acc, n) => acc + n);
}
//you have to call cast() method
N sum2<N extends num, T extends Iterable<N>>(T numbers) {
return numbers.cast<N>().reduce((acc, n) => acc + n);
}
void main() {
print(sum<int, List<int>>([1, 2, 3]));//specify types
print(sum2([1, 2, 3]));
}
Upvotes: 0