Почему я могу использовать » до » в первом аргументе Future.traverse, но не `до`?

#scala #scala-2.13

Вопрос:

Почему я могу использовать to для построения a Range для первого аргумента Future.traverse , но не until могу ? См. Следующий пример взаимодействия с консолью Scala.

 scala> Future.traverse(1 to 5)(Future.successful)
val res5: scala.concurrent.Future[IndexedSeq[Int]] = Future(<not completed>)

scala> Future.traverse(1 until 5)(Future.successful)
                                 ^
       error: Cannot construct a collection of type scala.collection.immutable.AbstractSeq[Int] with elements of type Int based on a collection of type scala.collection.immutable.AbstractSeq[Int].

scala> res5
val res7: scala.concurrent.Future[IndexedSeq[Int]] = Future(Success(Vector(1, 2, 3, 4, 5)))

scala>
 

Обратите внимание, что я использую Scala 2.13.5 для консоли, хотя Scala 2.13.2, похоже, ведет себя так же.

Как бы то ни было, я заметил, что to возвращается Range.Inclusive , и until возвращается Range.Exclusive . Но оба они расширяются Range , поэтому я не понимаю, чем отличаются эти два типа, так что Future.traverse в качестве первого аргумента можно использовать один, но не другой.

Комментарии:

1. Похоже, это связано с открытой ошибкой , о которой сообщалось много лет назад. Проблема, похоже, исчезла в Scala 3.

2. Как бы то ни было, явная подпись типа исправит это. Future.traverse[Int, Int, IndexedSeq](1 until 5)(Future.successful) работает.

3. Милые. Спасибо! Похоже, что сигнатура типа Range , начинающаяся с расширения AbstractSeq , а не IndexedSeq на самом деле, имела значение.

4. @LeoC Да, я думаю, что в этом ты прав!

Ответ №1:

Это выглядит как сочетание нескольких проблем.

1 until 5 возвращает a scala.collection.immutable.Range , в то время 1 to 5 как возвращается Range.Inclusive .

 scala> val exclusive: Range.Exclusive = 1 until 5
                                          ^
       error: type mismatch;
        found   : scala.collection.immutable.Range
        required: Range.Exclusive

scala> val inclusive: Range.Inclusive = 1 to 5
val inclusive: Range.Inclusive = Range 1 to 5
 

Range.Inclusive является конкретным классом и scala.collection.immutable.Range является родителем обоих Range.Inclusive и Range.Exclusive . Похоже, что это связано с открытой ошибкой, о которой упоминал Лео Си, scala.collection.immutable.Range рассматриваемой только AbstractSeq , а не IndexedSeq (как предполагал комментарий Сильвио Майоло). И AbstractSeq не может быть сконструирован. Range.Inclusive , будучи конкретным классом, не имеет такой же проблемы.

На данный момент я не уверен, почему AbstractSeq это невозможно построить. Я думал , что причина в том, что AbstractSeq это abstract так, но IndexedSeq это тоже черта характера. Тем не менее, это, вероятно, по замыслу AbstractSeq не может быть построено, но IndexedSeq может.