scala 2.13 自动隐式解析错误
scala 2.13 auto implicit resolution error
我正面临这个与 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
}
当type-checkingnew C(1)
时,编译器将预期的类型String
下推为type
检查表达式 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)
}
我正面临这个与 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
}
当type-checkingnew C(1)
时,编译器将预期的类型String
下推为type
检查表达式 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)
}