Scala: Why is the PECS principle not applied to Function1?
scala
Solution
Joshua is correct, and so is Scala. In fact, Scala mandates this rule, so you don't need to worry about it. Java, because it doesn't have variance annotations and has to make do with existentials at the call site, needs them to guide the programmers as to the correct design.
Scala has variance annotations at the definition site, while java has existentials at the call site. The output of the call is the input of the definition, and vice versa.
A `Function1` is not reading from its parameter, or writing to its result, which is what `reduce` is doing on Joshua's example. Instead you have to think of `Function1` as a collection.
When you write to a collection, that collection is a consumer. Similarly to a function: when you call it, you are writing to it. So, the input parameter, which is being written to, must be contra-variant.
Likewise, when you read from a collection, that collection is a producer. You read a function by look at its result, so the output parameter must be co-variant.
As you see, that is exactly `Function1` notation.
Problem
In Effective Java, Joshua Bloch discusses the principle of PECS (Producer-Extends, Consumer-Super). My understanding of this is that to increase API flexibility, the input (a collection that produces) should be made covariant and the output (collection that consumes) should be contravariant. A function that implements this principle can have the following signature: ``` private static void func( ArrayList<? extends Object> input, ArrayList<? super Integer> output) ``` However, in Scala, the Function1 trait has the following signature: ``` trait Function1[-T1, +R] extends AnyRef ``` T1 (the input type) is contravariant while the R (output type) is covariant. Is my understanding correct? If so, why is PECS not applied in Scala's Function1 trait?