泛型类型的隐式转换?

Posted

技术标签:

【中文标题】泛型类型的隐式转换?【英文标题】:Implicit conversion for generic type? 【发布时间】:2013-12-22 12:03:44 【问题描述】:

考虑这个功能:

def justTrue[T, S](seq: S)(implicit ev: S <:< Seq[T]) = true
justTrue(List(1,2,3))
>> true

它有效。但是为什么不能用同一个签名作为隐式转换呢?

implicit class TruthTeller[T, S](seq: S)(implicit ev: S <:< Seq[T]) 
  def justTrue = true

List(1,2,3).justTrue
>> error: Cannot prove that List[Int] <:< Seq[T].

隐式转换不只是一个函数吗?

【问题讨论】:

确实很奇怪。 val a = new TruthTeller(List(1,2,3)) 没问题。当您删除 type T 并使用 implicit ev: S &lt;:&lt; Seq[_] 时,它也可以工作 这正是我问这个问题的原因。我找到了一种解决方法(请参阅下面的答案),但我希望知道为什么原始代码不起作用。 【参考方案1】:

您完全正确,这应该在隐式 def/class 中同样有效。

这是一个错误,其中类型参数意外地从隐式视图的参数中进行类型推断:

SI-7944: type variables escape into the wild

现在从 2.11.0-M7 开始修复:

Welcome to Scala version 2.11.0-M7 (OpenJDK 64-Bit Server VM, Java 1.7.0_45).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :pa
// Entering paste mode (ctrl-D to finish)
implicit class TruthTeller[T, S](seq: S)(implicit ev: S <:< Seq[T]) 
  def justTrue = true

List(1,2,3).justTrue
// Exiting paste mode, now interpreting.

defined class TruthTeller
res0: Boolean = true

至于解决方法,有很多,你可以在你的答案中使用higher-kinded,或者例如从seq参数强制推断T

// the implicit ev isn't even needed here anymore
// but I am assuming the real use case is more complex
implicit class TruthTeller[T, S](seq: S with Seq[T])(implicit ev: S <:< Seq[T]) 
  def justTrue = true

// S will be inferred as List[Int], and T as Int
List(1,2,3).justTrue

【讨论】:

感谢您指出这是一个错误!【参考方案2】:

我找到的最佳解决方案:

import scala.language.higherKinds
implicit class TruthTeller[T, S[T] <: Seq[T]](seq: S[T]) 
  def justTrue = true

List(1,2,3).justTrue
>> true

但我真的很想知道为什么原始代码不起作用。

【讨论】:

以上是关于泛型类型的隐式转换?的主要内容,如果未能解决你的问题,请参考以下文章

结果类型是泛型类型上的类型投影的隐式转换

使用接口的隐式运算符

JavaScript的数据类型的隐式转换

25.scala的隐式转换

C的隐式类型转换

Scala中的隐式转换|理解