Why can't the compiler determine (_>: T) => (_ <: V [_ <: U]) <: T => V [U] for V [+ _]?

So, I played a little while trying to write something about existentiality and variance, and I came across this interesting piece of code.

final case class Box[+T](val value: T) {
  def >>=[U](f: T => Box[U]) = f(value)
  def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>= f
}

This will not compile:

Variance.scala:3: no type parameters for method >>=: (f: T => Box[U])Box[U] exist so that it can be applied to arguments (_$1 => _$2)
 --- because ---
argument expression type is not compatible with formal parameter type;
 found   : _$1 => _$2 where type _$2 <: Box[_ <: U], type _$1 >: T
 required: T => Box[?U]
  def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>= f
                                                                   ^
Variance.scala:3: type mismatch;
 found   : _$1 => _$2 where type _$2 <: Box[_ <: U], type _$1 >: T
 required: T => Box[U]
  def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>= f
                                                                       ^

which I find strange rather than a (_ >: T) => (_ <: Box[_ <: U])subtype T => Box[U]? Since it Function1is contravariant in the parameter of the first type, this is a subtype T => (_ <: Box[_ <: U]). Since it Function1is covariant in the type of result, it is a subtype T => Box[_ <: U], and since it Boxis covariant in its parameter, is this not the whole thing a subtype T => Box[U]?

Strange changing the code to

// This change is not required ;)
type Box[T] = `What A Category Theorist Calls "The Identity Monad" And What Everyone Else Calls "A Box"`[T]
final case class `What A Category Theorist Calls "The Identity Monad" And What Everyone Else Calls "A Box"`[+T](val value: T) {
  def >>=[U](f: T => Box[U]) = f(value)
  def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>= (f: T => Box[U])
}

"" , f: T => Box[U] . , ?

, , ,

def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this.>>=[U](f)

, , (_ >: T) => (_ <: Box[_ <: U]) <: T => Box[U] , >>=, , , , .

( Scala 2.12.1 ( sbt, - ))

+4
1
final case class Box[+T](val value: T) {
  def >>=[U](f: T => Box[U]) = f(value)
  def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>= f
}

flatMap Box[U], this >>= f.

>>= f type (_ >: T) => (_ <: Box[_ <: U]).

Box[(_ >: T) => (_ <: Box[_ <: U])] Box[U].

, :
def flatMap[U](f: (_ >: T) => (_ <: Box[_ <: U])): Box[U] = this >>=[U] f

0

Source: https://habr.com/ru/post/1664119/


All Articles