Scala 隐式搜索深度

7 浏览
0 Comments

Scala 隐式搜索深度

一个简单的例子:

class A
class B
class C
object testobject {
  val a = new A
  implicit def b(a:A):B = new B
  implicit def c(b:B) = new C
  val b:B = a
  val c:C = a 
}

最后一行无法通过编译。虽然我们已经定义了A=>B和B=>C的隐式转换,但它并不能推断出A=>C。

能够使隐式转换的层级工作将是非常好的。

我的特定问题,太长无法完整发布,实际上来自于一个Web框架。我想做如下的操作:

A => Secure[A] => Format[A]

使用以下定义:

implicit def secure[A](a:A):Secure[A] = ???
implicit def format[A](sec:Secure[A]):Format[A] = ???

所以我想通过隐式魔法来处理安全性和格式化,并且只有安全的输出才能进行格式化。

有人发现任何技巧可以使这个工作吗?

0
0 Comments

在Scala中,implicit关键字用于定义隐式转换。通过隐式转换,编译器可以自动地将一种类型转换为另一种类型,从而使代码更简洁、更易读。然而,有时候在使用隐式转换时会遇到一个问题,即Scala的隐式转换深度(implicit search depth)的限制。

隐式转换深度是指编译器在查找可用的隐式转换时所能够往上追溯的最大层数。Scala的编译器默认限制隐式转换的深度为2层,也就是说,编译器只会查找直接的隐式转换,而不会继续往上查找更多层的隐式转换。这就导致了一个问题,即当我们使用链式的隐式转换时,如果超过了编译器的隐式转换深度限制,编译器将无法找到合适的隐式转换。

为了解决这个问题,我们可以使用额外的隐式参数来实现所需的效果。通过在方法或函数的参数列表中添加额外的隐式参数,我们可以告诉编译器在查找隐式转换时继续往上查找。这样,编译器就能够找到所需的隐式转换,从而解决了隐式转换深度的限制。

下面是一个示例代码,展示了如何使用额外的隐式参数来解决隐式转换深度的限制:

object ImplicitSearchDepthExample {
  implicit def intToString(i: Int): String = i.toString
  implicit def stringToDouble(s: String): Double = s.toDouble
  def printDouble(d: Double)(implicit s: String): Unit = {
    println(d)
    println(s)
  }
  def main(args: Array[String]): Unit = {
    val i: Int = 42
    printDouble(i)
  }
}

在上面的示例中,我们定义了两个隐式转换,将Int类型转换为String类型,将String类型转换为Double类型。然后,我们定义了一个printDouble方法,该方法接受一个Double类型的参数和一个隐式的String类型的参数。在main方法中,我们传入一个Int类型的参数调用printDouble方法。由于编译器的隐式转换深度限制,默认情况下编译器只会查找直接的隐式转换,所以编译器无法找到隐式转换将Int类型转换为Double类型。但是,由于我们在printDouble方法的参数列表中添加了一个隐式的String类型的参数,编译器会继续往上查找隐式转换,最终找到将Int类型转换为String类型的隐式转换,然后再找到将String类型转换为Double类型的隐式转换,从而成功地将Int类型的参数转换为Double类型的参数。

总之,Scala的隐式转换深度限制可能会导致在使用链式的隐式转换时出现问题。为了解决这个问题,我们可以使用额外的隐式参数来实现所需的效果,告诉编译器在查找隐式转换时继续往上查找。通过这种方式,我们可以绕过编译器的隐式转换深度限制,成功地进行链式的隐式转换。

0