我想做以下事情:
val foo = List[B <% JValue] = 42 :: "hello" : Nil
让编译器知道我的列表成员可以转换为JValue
s。
但是,这不会编译。我无法满足于List[Any]
,因为我必须使用其成员,其中可以转换为JValues的值,例如:
def fun[A <% JValue](x: List[A]) = ...
有什么方法可以解决这个问题吗?
答案 0 :(得分:5)
你可以写
val foo: List[JValue] = List(42, "hello")
如果没有从这些类型到JValue
的隐式转换,那么它将不会键入check。
不幸的是你不能把它写成42 :: "hello" :: Nil
,因为编译器不够聪明,不知道你想在每个术语上应用转换(你可以在每个术语上添加一个类型注释,但这很麻烦)。每个::
方法都必须以某种方式一直向前看到表达式的结尾,以检查某个后来的方法是否使其适合类型参数。
但是,如果您想添加自己的时髦运算符,则可以约束::
允许的类型:
implicit class pimp(xs: List[JValue]) {
def |: (x: JValue) = x :: xs
}
之后你可以写这样的东西:
val foo = 42 |: "hello" |: Nil
// type is List[JValue]
(我尝试对其进行参数化,以便它可以推断出最具体的常见类型,如::
所做的那样,但是使用上限,编译器不想玩球 - see here。也许有人如果可能的话,更多Scala-fu可以修复它。)
答案 1 :(得分:2)
Luigi Plinge answer的|:
方法略有改进:
你可以写
val foo: List[JValue] = 42 :: "hello" :: HNil
使用适当的隐式转换(使用shapeless):
import shapeless._
trait HListTConv[H <: HList, T] {
def apply(l: List[T], hl: H): List[T]
}
object HListTConv {
implicit def apply0[T] = new HListTConv[HNil, T] {
def apply(l: List[T], hl: HNil): List[T] = l
}
implicit def applyN[Head, Tail <: HList, T](implicit c: HListTConv[Tail, T], conv: Head => T) =
new HListTConv[Head :: Tail, T] {
def apply(l: List[T], hl: Head :: Tail): List[T] = (hl.head: T) :: c(l, hl.tail)
}
}
implicit def hListToJValueList[H <: HList](hl: H)(implicit c: HListTConv[H, JValue]): List[JValue] = c(Nil, hl)
测试:
case class Test(s: String)
implicit def intToTest(i: Int): Test = Test(i.toString)
implicit def strToTest(s: String): Test = Test(s)
implicit def hListToListTest[H <: HList](hl: H)(implicit c: HListTConv[H, Test]): List[Test] = c(Nil, hl)
scala> val foo: List[Test] = 42 :: "hello" :: HNil
foo: List[Test] = List(Test(42), Test(hello))
答案 2 :(得分:0)
您可以使用一组简单的含义来启用转换。
class JValue
implicit intToJValue(x: Int) = new JValue
implicit stringToJValue(x: String) = new JValue
val xs: List[JValue] = List(1, "hello")
对于第二个问题,您可以通过以下方式启用批量清单转换:
implicit def listToJList[A <% JValue](xs: List[A]): List[JValue] = xs
def foo[A <% JValue](x: List[A]): List[JValue] = x
以上示例仅在您具有统一类型时才有效,否则您将需要采用更复杂的方法,在大多数情况下,异构类型列表将统一到List [Any]。
你可以使用无形的方式提出更优雅/更复杂的解决方案,大多数采用shapless.Poly和HList's。