如何解决 Scala 中重载解析的限制?
在Scala中,重载和隐式参数解析的相互作用似乎使得下面的代码无法使用。
trait Bijection[A, B] extends Function1[A, B] with Unapply[A, B] { self =>
def apply(a: A): B
def unapply(b: B): A
}
sealed trait Unapply[A, B] {
def unapply(b: B): A
}
object Bijection {
implicit def biject[A](a: A): Biject[A] = new Biject(a)
implicit object IntStringBijection extends Bijection[Int, String] {
override def apply(a: Int): String = a.toString
override def unapply(b: String): Int = b.toInt
}
}
sealed class Biject[A](a: A) {
def as[B](implicit f: Function1[A, B]): B = f(a)
def as[B](implicit f: Unapply[B, A]): B = f unapply a
}
这里的目标是 a.as[B] 执行类型安全转换,无论 Bijection[A,B] 还是 Bijection[B,A] 在隐式作用域中是否可用。
这不起作用的原因是隐式解析似乎是在编译器中重载消歧之后发生的,并且由于“as”的两个实现具有相同的结果类型,因此编译器甚至不会尝试找出答案适当的隐式是否在可以执行转换的范围内。简而言之,在重载消歧中不使用隐式解析。
我想要重载“as”的原因是避免该库的用户需要在调用站点对双射的“方向”进行编码;显然,可以这样实现 Biject:
sealed class Biject[A](a: A) {
def viaForward[B](implicit f: Function1[A, B]): B = f(a)
def viaReverse[B](implicit f: Unapply[B, A]): B = f unapply a
}
但这确实没有吸引力,因为它本质上使皮条客变得多余;人们也可以显式地传递双射,但是这样一来,您当然就失去了使所使用的双射根据范围而变化的能力。
对于这个问题有什么好的解决办法吗?
In Scala, the interaction of overloading and implicit argument resolution seem to make it impossible to make the following code usable.
trait Bijection[A, B] extends Function1[A, B] with Unapply[A, B] { self =>
def apply(a: A): B
def unapply(b: B): A
}
sealed trait Unapply[A, B] {
def unapply(b: B): A
}
object Bijection {
implicit def biject[A](a: A): Biject[A] = new Biject(a)
implicit object IntStringBijection extends Bijection[Int, String] {
override def apply(a: Int): String = a.toString
override def unapply(b: String): Int = b.toInt
}
}
sealed class Biject[A](a: A) {
def as[B](implicit f: Function1[A, B]): B = f(a)
def as[B](implicit f: Unapply[B, A]): B = f unapply a
}
The goal here is for a.as[B] to perform a typesafe conversion irrespective of whether a Bijection[A,B] or a Bijection[B,A] is available in implicit scope.
The reason that this doesn't work is that implicit resolution appears to take place after overload disambiguation in the compiler, and since both implementations of 'as' have the same result type, the compiler doesn't even get around to attempting to find out whether an appropriate implicit is in scope that can perform the conversion. In short, implicit resolution is not used in overload disambiguation.
The reason I want to have 'as' overloaded is to avoid the need for the user of this library to need to encode the "direction" of the bijection at the call site; obviously one could implement Biject as this:
sealed class Biject[A](a: A) {
def viaForward[B](implicit f: Function1[A, B]): B = f(a)
def viaReverse[B](implicit f: Unapply[B, A]): B = f unapply a
}
but this is really unappealing because it essentially makes the pimp superfluous; one might as well explicitly pass the bijection, but then of course you lose the ability to have the bijection that is used vary based upon the scope.
Is there any good solution to this problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这怎么样?
How's this?