在scala中,可以在Seq
中转换变量,但如果我使用Seq
构造::
则不起作用。例如
case class A(s: String)
implicit def toA(s: String): A = A(s)
val Seq(a, b, c, d): Seq[A] = Seq("a", "b", "c", "d") // compiles
val Seq(e, f): Seq[A] = "e" :: "f" :: Nil // won't compile
Seq("a","b","c","d")
实际上是Seq.apply[X]("a","b","c","d")
,其中X
被推断为左侧的A
。在Seq.apply[A](...
中,A
类型的元素是预期的,因此字符串通过A
隐式转换为toA
(所以它实际上是val Seq(a, b, c, d): Seq[A] = Seq.apply[A](A("a"), A("b"), A("c"), A("d"))
)。
但"e" :: "f" :: Nil
实际上是::[Y]("e", ::[Z]("f", Nil))
,其中Z
首先被推断为>: String
,其次Y
被推断为>: String
所以它是>: List[String]
类型(实际上是List[Serializable]
)并且它与类型模式Seq[A]
不匹配。所以有编译错误。
基本上,你有一个从String
到A
的隐式转换,但不是从Seq[String]
到Seq[A]
。
如果你只写val Seq(e,f) = "e" :: "f" :: Nil
然后这个编译,因为右侧匹配左侧的模式。
此外val Seq(f): Seq[A] = "f" :: Nil
编译,因为在::[Z]("f", Nil)
只有一个类型参数,它可以推断为等于A
。
这里的问题是编译器没有理由应用隐式转换,直到为时已晚。表达方式
"e" :: "f" :: Nil
创建一个与List[String]
不兼容的Seq[A]
,这会导致错误。
要解决此问题,您需要从List[String]
到List[A]
进行隐式转换。
请注意,这也不起作用:
"e" :: "f" :: List[A]()
你可以添加一个String
到List[A]
所以它不会隐式转换为A
为你,你最终得到List[Serializable]
。
Error:(15, 31) type mismatch;
found : List[java.io.Serializable]
required: Seq[Main.A]
val Seq(e, f): Seq[A] = "e" :: "f" :: Nil
所以我猜这很明显是一个类强制转换异常