在scala List ::不做隐式转换

时间:2019-03-22 12:29:23

标签: scala implicit-conversion

在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

3 个答案:

答案 0 :(得分:2)

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]不匹配。因此存在编译错误。

基本上,您是从StringA的隐式转换,而不是从Seq[String]Seq[A]的转换。

如果您只写val Seq(e,f) = "e" :: "f" :: Nil,那么它将编译,因为右侧匹配左侧的模式。

val Seq(f): Seq[A] = "f" :: Nil也会进行编译,因为在::[Z]("f", Nil)中只有一个类型参数,并且可以将其推断为等于A

答案 1 :(得分:0)

这里的问题是,编译器没有理由应用隐式转换,直到为时已晚。表达式

"e" :: "f" :: Nil 

创建一个与引起错误的List[String]不兼容的Seq[A]

要解决此问题,您需要从List[String]List[A]进行隐式转换。

请注意,此无效

"e" :: "f" :: List[A]()

您可以在String上添加List[A],这样它就不会隐式转换为A,最终得到List[Serializable]

答案 2 :(得分:-3)

Error:(15, 31) type mismatch;
 found   : List[java.io.Serializable]
 required: Seq[Main.A]
  val Seq(e, f): Seq[A] = "e" :: "f" :: Nil

所以我想这显然是类强制转换异常