В Scala List :: не делает неявного преобразования - PullRequest
0 голосов
/ 22 марта 2019

В 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 ]

2 голосов
/ 22 марта 2019

Seq("a","b","c","d") на самом деле Seq.apply[X]("a","b","c","d"), где X подразумевается как A с левой стороны. А в Seq.apply[A](... ожидаются элементы типа A, поэтому строки неявно преобразуются в A s через 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.

0 голосов
/ 22 марта 2019
Error:(15, 31) type mismatch;
 found   : List[java.io.Serializable]
 required: Seq[Main.A]
  val Seq(e, f): Seq[A] = "e" :: "f" :: Nil

Так что, я думаю, это очевидное исключение для класса

0 голосов
/ 22 марта 2019

Проблема здесь в том, что у компилятора нет причин применять неявное преобразование до тех пор, пока не станет слишком поздно. Выражение

"e" :: "f" :: Nil 

создает List[String], который несовместим с Seq[A], что вызывает ошибку.

Чтобы исправить это, вам необходимо выполнить неявное преобразование из List[String] в List[A].

Обратите внимание, что тоже не работает :

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

Вы можете добавить String к List[A], чтобы он не явным образом конвертировался в A для вас, и в итоге вы получите List[Serializable].

...