仅存在隐式转换,尽管从未应用,但仍可以编译程序

问题描述 投票:4回答:1

由类型构造函数f和适当类型F[_]参数化的考虑方法A

def f[F[_], A](v: F[A]) = v

让我们尝试将其应用于new Bar

scala> class Bar
class Bar

scala> def f[F[_], A](v: F[A]) = v
def f[F[_], A](v: F[A]): F[A]

scala> f(new Bar)
       ^
       error: no type parameters for method f: (v: F[A]): F[A] exist so that it can be applied to arguments (Bar)
        --- because ---
       argument expression's type is not compatible with formal parameter type;
        found   : Bar
        required: ?F[?A]
         ^
       error: type mismatch;
        found   : Bar
        required: F[A]

Bar的错误形状不正确。

现在让我们添加从BarList[Int]的隐式转换>

scala> implicit def barToList(b: Bar): List[Int] = List(42)
def barToList(b: Bar): List[Int]

scala> f(new Bar)
val res1: Any = Bar@56881196

但是,请注意,由于res1的运行时类是Bar,而不是List,因此似乎并未实际应用隐式转换。此外,res1的编译时类型是Any,而不是List[Int]。查看-Xprint:typer的输出,我们看到类似

val res1: Any = f[Any, Nothing](new Bar())

我们看到以下推论的地方

F[_] = Any
A = Nothing 

相对于

F[_] = List
A = Int 

并且我们看到实际上没有发生任何转换,也就是说,我们没有看到类似的东西

f(barToList(new Bar()))

为什么仅隐式转换的存在使程序得以编译,而实际上未应用任何隐式转换?请注意,当明确说明类型参数时,它会按预期工作]

scala> f[List, Int](new Bar)
val res2: List[Int] = List(42)

考虑方法f,它由类型构造函数F [_]和适当的类型A参数化def f [F [_],A](v:F [A])= v让我们尝试将其应用于新的Bar scala > class Bar class Bar scala> def f [F [...

scala type-inference implicit-conversion type-parameter type-constructor
1个回答
0
投票

我之前已经注意到此问题,我认为可以在编译器中将其追溯到this code

  // Then define remaining type variables from argument types.
  foreach2(argtpes, formals) { (argtpe, formal) =>
    val tp1 = argtpe.deconst.instantiateTypeParams(tparams, tvars)
    val pt1 = formal.instantiateTypeParams(tparams, tvars)

    // Note that isCompatible side-effects: subtype checks involving typevars
    // are recorded in the typevar's bounds (see TypeConstraint)
    if (!isCompatible(tp1, pt1)) {
      throw new DeferredNoInstance(() =>
        "argument expression's type is not compatible with formal parameter type" + foundReqMsg(tp1, pt1))
    }
  }
  val targs = solvedTypes(tvars, tparams, varianceInTypes(formals), upper = false, lubDepth(formals) max lubDepth(argtpes))
© www.soinside.com 2019 - 2024. All rights reserved.