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

Scala自动选择隐式方法

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

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

为此:-

  val w: Seq[(AImpl,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,该表达式失败。在上面的行中,键入检查ci的预期类型 C[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)
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...