scala 2.13 自动隐式解析错误

Div*_*shu 1 scala implicit scala-collections scala-2.13

我正面临这个与 Scala 隐式解析相关的奇怪问题

这是代码片段

import scala.collection.Factory
import scala.collection.immutable.Seq

sealed trait A

sealed trait B

case class BImpl() extends B

case class AImpl() extends A

object implicitsContainer {

  type AB = (A, B)

  implicit def toStringAnyTuples[C[X] <: Iterable[X], A <: AB]
  (col: C[A])
  (implicit factory: Factory[(String, Any), C[(String, Any)]])
  : C[(String, Any)] = {

    factory.fromSpecific(col.iterator.map(f => f._1.toString -> f._2))
  }
}

object Main extends App {

  import implicitsContainer._

  def a(f: Seq[(String, Any)]): Seq[(String, Any)] = f

  val w: Seq[(AImpl, BImpl)] = Seq(AImpl() -> BImpl())

  val x: Seq[(String, Any)] = a(w)

  //    Won't compile
  //    val y: Seq[(String, Any)] = a(Seq(AImpl() -> BImpl()))
}
Run Code Online (Sandbox Code Playgroud)

Scala 自动拾取隐式方法

implicit def toStringAnyTuples[C[X] <: Iterable[X], A <: AB](col: C[A])
  (implicit factory: Factory[(String, Any), C[(String, Any)]])
  : C[(String, Any)] = {

    factory.fromSpecific(col.iterator.map(f => f._1.toString -> f._2))
  }
Run Code Online (Sandbox Code Playgroud)

为了这: -

  val w: Seq[(AImpl, BImpl)] = Seq(AImpl() -> BImpl())

  val x: Seq[(String, Any)] = a(w)
Run Code Online (Sandbox Code Playgroud)

但为此引发错误

val y: Seq[(String, Any)] = a(Seq(AImpl() -> BImpl()))
Run Code Online (Sandbox Code Playgroud)

错误是:-

Error:(44, 47) type mismatch;
 found   : (AImpl, BImpl)
 required: (String, Any)
    val y: Seq[(String, Any)] = a(Seq(AImpl() -> BImpl()))
Run Code Online (Sandbox Code Playgroud)

还有一点,如果我从w 中删除类型

  val w = Seq(AImpl() -> BImpl())

  val x: Seq[(String, Any)] = a(w)
Run Code Online (Sandbox Code Playgroud)

那么这也可以正常工作。唯一的错误是

val y: Seq[(String, Any)] = a(Seq(AImpl() -> BImpl()))
Run Code Online (Sandbox Code Playgroud)

我在用: -

SCALA -> 2.13.3

SBT -> 1.3.13

爪哇 -> 14

Dmy*_*tin 5

这只是类型推断问题。Seq.apply未推断出 的类型参数。尝试

val y: Seq[(String, Any)] = a(Seq[(AImpl, BImpl)](AImpl() -> BImpl()))
Run Code Online (Sandbox Code Playgroud)

或者

val y: Seq[(String, Any)] = a(Seq[(A, B)](AImpl() -> BImpl()))
Run Code Online (Sandbox Code Playgroud)

  • @Divyanshu 不确定。当未推断某些类型时,为编译器提供提示(例如显式指定类型参数或类型归属)是改进 Scala 中类型推断的标准方法。也不推荐隐式转换(与隐式的其他用法相反)。 (2认同)