scala / docs.scala-lang

The Scala Documentation website
http://docs.scala-lang.org
563 stars 1.03k forks source link

Fixed types-variance.md contravariant example code comment #2938

Open still-dreaming-1 opened 10 months ago

still-dreaming-1 commented 10 months ago

Fixed the second code comment for the last example just before the summary. The words "Book" and "Buyable" needed to be swapped. This makes it consistent with how the first comment uses the term "expected", where "expected" refers to the type you see in the following line of code. The first code comment is referring to the return type in the next line of code. The second comment is referring to the parameter type in the following line of code. Therefore, in the second code comment, "Book" is what is "expected" (by the h type), and "Buyable" is what is "provided" by the f parameter type.

still-dreaming-1 commented 10 months ago

If I am mistaken about how these terms are used, then the first code comment needs to be changed. Either way, the current code comments are inconsistent and confusing. The way they currently read sounds like it is applying covariant logic to both explanations, even though the parameter/consumer type is and should be contravariant and the return/producer type is and should be covariant.

joroKr21 commented 10 months ago

expected here refers to the definition of f:

val f: Function[Buyable, Buyable] = b => b

So it both expects and returns a Buyable. Does that make more sense now?

joroKr21 commented 10 months ago

You can try to extend the sentence with the verb used:

// OK to return a Buyable where an Item is expected **to be returned**
// OK to provide a Book where a Buyable is expected **to be provided**
still-dreaming-1 commented 10 months ago

It seems to me that "expected" should consistently refer either a type in f or a type in the line of code following the comment (a type in g or h). I don't think it is good for the meaning of the term "expected" to change in these two comments.

Here is the complete example with both comments:

val f: Function[Buyable, Buyable] = b => b

// OK to return a Buyable where a Item is expected
val g: Function[Buyable, Item] = f

// OK to provide a Book where a Buyable is expected
val h: Function[Book, Buyable] = f

The first comment is comparing the return type of g to the return type of f. If "expected" refers to the type in g it is correct, but if it refers to the type in f it is wrong.

The second comment is comparing the parameter type of h to the parameter type of f. If "expected" refers to the type in h, it is wrong, but if it refers to the type in f it is correct.

I don't think swapping the meaning of "expected" between these two comments is helpful because it makes it sound like a line of reasoning rather than a statement of what is or how the language works. Then it can become confusing because it sounds like it is using covariant reasoning to defend contravariant types by always putting the more specific type first. This could imply that the reason it makes sense is because a "Buyable" is an "Item" (which intuitively makes sense), and that "Book" is a "Buyable" (which also intuitively makes sense, and thus is misleading).

still-dreaming-1 commented 10 months ago

Perhaps the types should be flipped in the first comment instead of the second. Also, changing the word "OK" to "Allowed" would go even further in the direction of making these sound like statements of what is / how it works, rather than a line of reasoning.

SethTisue commented 8 months ago

@joroKr21 care to respond further?

joroKr21 commented 8 months ago

Well I think it's precisely the variance that determines in which direction to apply "expected". Let's say we expect a type F[A] and provide a type F[B]