我想這樣做如下:如何給Scala編譯器證明集合具有正確類型的元素?
val foo = List[B <% JValue] = 42 :: "hello" : Nil
編譯器知道我的列表的成員可以轉換爲JValue
秒。
然而,這並不編譯。我不能滿足於一個List[Any]
因爲我有利用其成員在那裏可以轉換成JValues值預計,在說:
def fun[A <% JValue](x: List[A]) = ...
有什麼辦法解決?
我想這樣做如下:如何給Scala編譯器證明集合具有正確類型的元素?
val foo = List[B <% JValue] = 42 :: "hello" : Nil
編譯器知道我的列表的成員可以轉換爲JValue
秒。
然而,這並不編譯。我不能滿足於一個List[Any]
因爲我有利用其成員在那裏可以轉換成JValues值預計,在說:
def fun[A <% JValue](x: List[A]) = ...
有什麼辦法解決?
你可以寫
val foo: List[JValue] = List(42, "hello")
如果從這些類型JValue
,那麼它不會鍵入檢查的隱式轉換。
不幸的是,你不能將它寫爲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的人可以修復它,如果它是poss IBLE。)
是[這個答案](http://stackoverflow.com/a/17519454/406435)斯卡拉足夠了嗎? – senia
您可以使用一組簡單的含義來啓用轉換。
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來提出更優雅/複雜的解決方案。
從|:
的方法稍加改進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))
HLists? (https://github.com/milessabin/shapeless) – adelbertc
什麼是錯誤信息?你試過嗎?(42:JValue)::(「hello」:JValue):: Nil'? – huynhjl