scala2.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()))
}

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))
}

为此:-

val w: Seq[(AImpl, BImpl)] = Seq(AImpl() -> BImpl())
val x: Seq[(String, Any)] = a(w)

但是为这个抛出了一个错误

val y: Seq[(String, Any)] = a(Seq(AImpl() -> BImpl()))

错误为:-

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

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

val w = Seq(AImpl() -> BImpl())
val x: Seq[(String, Any)] = a(w)

那么这也会很好。唯一的错误是

val y: Seq[(String, Any)] = a(Seq(AImpl() -> BImpl()))

我正在使用:-

SCALA->2.13.3

SBT->1.3.13

JAVA->14

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

val y: Seq[(String, Any)] = a(Seq[(AImpl, BImpl)](AImpl() -> BImpl()))

val y: Seq[(String, Any)] = a(Seq[(A, B)](AImpl() -> BImpl()))

您所经历的是Scala编译器中推理工作方式的症状。下面是一个显示相同问题的较小示例:

object Test {
class C[T](x: T)
implicit def conv(c: C[Int]): C[String] = ???
def m(cs: C[String]) = 1
val ci = new C(1)
def t1: Int = m(ci)       // OK
def t2: Int = m(new C(1)) // found: Int, expected: String
}

当类型检查new C(1)时,编译器将预期的类型String下推为检查表达式1,该表达式失败。在上面的行中,键入检查具有预期类型的ciC[String]的成功得益于隐式转换。我在这里的建议是定义一个执行转换的扩展方法使转换隐含。为了清晰起见,也建议这样做——隐式转换,如示例中定义的问题可能会导致令人惊讶的、难以诊断的问题。在我的例子中,它看起来是这样的:

object Test {
class C[T](x: T)
implicit class CExt(private val c: C[Int]) extends AnyVal {
def toCString: C[String] = ???
}
def m(cs: C[String]) = 1
val ci = new C(1)
def t1: Int = m(ci.toCString)
def t2: Int = m(new C(1).toCString)
}

相关内容

  • 没有找到相关文章

最新更新