Implicit class resolution for parameterized types

In the following example, it seems that the Scala compiler recognizes an implicit class when it is defined to take a higher view Wrapper. Why is this?

scala> case class Nested(n: Int)
defined class Nested

scala> case class Wrapper[A <: Product](nested: A)
defined class Wrapper

scala> implicit class I1[W <: Wrapper[A], A <: Product](underlying: W) {
     | def ok1() = true
     | }
defined class I1

scala> Wrapper(Nested(5)).ok1()
<console>:26: error: value ok1 is not a member of Wrapper[Nested]
       Wrapper(Nested(5)).ok1()
                          ^
scala> implicit class I2[W <: Wrapper[_]](underlying: W) {
     | def ok2() = true
     | }
defined class I2

scala> Wrapper(Nested(5)).ok2()
res1: Boolean = true

Is there a workaround for implicit permission that supports full information about a nested type, allowing you to attach type data to it, for example TypeTag?

Note. The above example shows that Nestedthey Wrapperapply to class classes, but they are not an integral part of the question. It's just a convenience for a shorter and simpler console session.

+4
source share
2 answers

- Scala. . SI-2272.

, A. , -Xlog-implicits. , A Nothing:

I1 is not a valid implicit value for Test.w.type => ?{def ok: ?} because:
inferred type arguments [Wrapper[Nested],Nothing] do not conform to method I1 type parameter bounds [W <: Wrapper[A],A <: Product]

, I1 :

scala> val w = Wrapper(Nested(5))
w: Wrapper[Nested] = Wrapper(Nested(5))

scala> new I1(w)
<console>:21: error: inferred type arguments [Wrapper[Nested],Nothing] do not conform to class I1 type parameter bounds [W <: Wrapper[A],A <: Product]
       new I1(w)
       ^
<console>:21: error: type mismatch;
 found   : Wrapper[Nested]
 required: W
       new I1(w)
              ^

.

-, Wrapper - case, , . W underlying Wrapper[A]:

implicit class I1[A <: Product](underlying: Wrapper[A]) {
  def ok = true
}

, , W <:< Wrapper[A], W:

implicit class I1[W, A <: Product](underlying: W)(implicit ev: W <:< Wrapper[A]) {
  def ok = true
}
+4

, , . .

- , , , , Wrapper . (99% case, , case).

, , , - . , :

scala> trait Foo[A]; trait Bar extends Foo[Int]
defined trait Foo
defined trait Bar

scala> implicitly[Bar with Foo[Int] =:= Bar]
res0: =:=[Bar with Foo[Int],Bar] = <function1>

, :

implicit class I1[Y, A <: Product](underlying: Y with Wrapper[A]) {
  def ok1(): (Y, A) = ???
}

:

scala> :paste
// Entering paste mode (ctrl-D to finish)

case class Nested(n: Int)
case class Wrapper[A <: Product](nested: A)
class Crazy(override val nested: Nested) extends Wrapper[Nested](nested)

implicit class I1[Y, A <: Product](underlying: Y with Wrapper[A]) {
  def ok1(): (Y, A) = ???
}

// Exiting paste mode, now interpreting.


scala> :type Wrapper(Nested(5)).ok1()
(Wrapper[Nested], Nested)

scala> :type new Crazy(Nested(5)).ok1()
(Crazy, Nested)

, , , : , A .

+1

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


All Articles