如何解决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)
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。