我有以下代码,它应该采用函数A => Boolean
(输入类型的通用)并通过链式隐式转换将其转换为通用特征Y[A]
:
val f: Int => Boolean = ???
trait X[A] {
def m1: Unit
}
implicit def toX[A](f: A => Boolean): X[A] = ???
f.m1 // Works
trait Y[A] {
def m2: Unit
}
implicit def toY[T, A](x: T)(implicit toX: T => X[A]): Y[A] = ???
f.m2 // Won't compile
不幸的是,最后一行不会编译。
执行以下任何一次更改就足以使代码编译:
X
非通用Y
非通用Int => A
)Option[A]
,Seq[A]
或Array[A]
基于此,我的结论是隐式转换链不起作用,因为源类型(输入类型的泛型函数)是通用的,逆向和中间类型和目标类型( X[A]
和Y[A]
)是通用的。
关于如何解决这个问题的任何想法?
UPDATE:最终代码缩进,不仅可以处理作为源类型的函数,还可以处理其他类型的函数(Option[A]
,Seq[A]
,{{1}等等)。为实现这一目标,我们的想法是拥有A
函数的版本,将每种类型转换为toX
。然后只需要一个X[A]
版本。
答案 0 :(得分:6)
我想我有一个解决方案,请查看以下代码:
val f: Int => Boolean = _ => true
trait X[A] {
def m1: Unit
}
implicit def funcToX[A](f: A => Boolean): X[A] = new X[A] {
override def m1: Unit = println("Hello x")
}
f.m1 // Works
trait Y[A] {
def m2: Unit
}
implicit def toY[T[_,_], A](x: T[A, Boolean])(implicit toX: T[A, Boolean] => X[A]): Y[A] = new Y[A] {
override def m2: Unit = {
x.m1
println("Hello y")
}
}
f.m2 // now works
我在这里使用更高级的kinded类型语法。它是scala语言的高级功能,我没有足够的经验来解释它。转换为Y应该适用于任何只需要两个类型参数的类型(并且已经定义了转换" toX")。
问题是你真的需要转换为Y在参数T上是通用的吗?也许它足以让它接受函数作为参数:
implicit def toY[A](x: A => Boolean)(implicit toX: (A => Boolean) => X[A]) = ???
您可以阅读有关更高级别的类型的更多信息,例如此帖:
<强>更新强>
在提出作者要求后,我提出了以下解决方案:
type SingleGenericFun[T] = T => _
val f: SingleGenericFun[Int] = _ > 42
val g: Int = 42
trait X[A] {
def m1: Unit
}
implicit def toX(f: SingleGenericFun[Int]): X[Int] = ???
implicit def toX(x: Int): X[Int] = new X[Int] {
override def m1: Unit = println(x)
}
f.m1 // Works
trait Y[A] {
def m2: Unit
}
implicit def toY2[T[_, _], A](x: T[A, _])(implicit toX: T[A, Boolean] => X[A]): Y[A] = new Y[A] {
override def m2: Unit = {
x.m1
println("Hello y!")
}
}
implicit def toY0[A](x: A)(implicit toX: A => X[A]): Y[A] = new Y[A] {
override def m2: Unit = {
x.m1
println("Hello y!")
}
}
implicit def toY1[T[_], A](x: T[A])(implicit toX: T[A] => X[A]): Y[A] = new Y[A] {
override def m2: Unit = {
x.m1
println("Hello y")
}
}
g.m2
f.m2 // Compile
它仍然不是最好的解决方案,因为需要提供3种(或更多种)技术上做同样事情的方法,我不知道如何对其进行生成,也不知道如何在第一名。