1 Вопрос: Вывод типа параметра для лямбды (снова!)

вопрос создан в Thu, May 2, 2019 12:00 AM

Мне интересно, почему это не работает (отсутствует тип параметра)?

 Seq(1,2,3).toSet.map(_ + 1)

но это так:

 val foo = Seq(1,2,3).toSet
 foo.map(_ + 1)

а также это: (3)

  Seq(1,2,3).toSet[Int].map(_ + 1)

или это:

  Seq(1,2,3).toList.map(_ + 1)

Что особенного в toSet, который делает его потерянным в первом случае, а не во втором?

    
11
  1. Причуды компилятора Scala никогда не перестанут удивлять. Опять же, сам компилятор никогда не перестанет удивлять.
    2019-05-02 15: 04: 44Z
  2. кстати, такой проблемы нет для компилятора dotty
    2019-05-02 15: 24: 22Z
  3. @ BogdanVakulenko да, я боюсь, что dotty - это не стартер для меня из-за отсутствия проекций типа: (
    2019-05-02 15: 39: 14Z
  4. еще одна забавная вещь о toSet: Seq(1,2,3).toSet() - возвращает boolean
    2019-05-05 12: 20: 52Z
  5. @ БогданВакуленко бесценен: D
    2019-05-05 12: 47: 22Z
1 ответ                              1                         

Образованное предположение:

def toSet[B :> A]: Set[B]

против

def toList: List[A]

По какой-то причине toSet является параметрическим - если вы разделите toSet и map на два оператора, то в первом случае компилятор должен будет что-то предположить и присвоить этому типу val, а затем использовать 06003506262505050501100000000000000000000000000000000000000000000000000000000000000 р>

Но с B он догадывается, что есть какой-то A, который он затем должен отобразить ... что именно? Вы можете угадать тип map, только если знаете тип Seq(1,2,3).toSet.map.

Короче говоря, проблема B >: Int, кажется, является проблемой, так как если мы сделаем это:

_ * 2

это работает.

Я могу только догадываться, что это была некоторая попытка сделать ковариант _, которая привела к обратным результатам.

    
3
2019-05-02 23: 06: 14Z
  1. Тот же шаблон применяется к [B :> A], который также является
    implicit class AsSetOps[F, A](val fa: scala.collection.SeqLike[A, F]) {
      def asSet: Set[A] = fa.toSet[A]
    }
    Seq(1,2,3).asSet.map(_ * 2)
    
    . ссылка
    2019-05-03 10: 16: 43Z
  2. Похоже, что это довольно много времени назад. rel = "nofollow noreferrer"> ссылка Для toSet это может быть понятно, поскольку это изменчивая (инвариантная) коллекция, но для неизменяемой toBuffer она могла быть добавлена ​​случайно (?) (без проверки) ... и тогда он пробыл 8 лет. 2.13 все еще есть эта проблема 2019-05-03 10: 29: 42Z
  3. [B :> A] Ну да ... Но то же самое относится и к toBuffer, не так ли? Вы можете только угадать тип Set, если вы знаете тип набора. Кроме того, > You can guess the type of _ * 2 only if you know the type of _ является не ковариантным, и, даже если это так, я не вижу, какой тип возврата val foo = bar.toSet для другого объекта я> должен был бы сделать с этим: /
    2019-05-03 11: 17: 01Z
  4. Разница в том, что в одном случае компилятор вынужден принимать решение (разрешить foo), и, не имея дополнительных знаний, он предполагает, что Set (который, как я полагаю, является частным случаем в компилятор). Если вы делаете 2 ограничения одновременно, то вам нужно рассмотреть 2 случая, которые не описаны ни в одном конкретном случае. По сути, это угловой случай, когда система типов ломает логический вывод, которого не должно быть в Dotty. У меня было несколько других подобных лет.
    2019-05-03 11: 21: 37Z
  5. Если задуматься, вся идея шаблона Aux заключается в том, что компилятор не может обрабатывать подобные случаи - требуется выяснить тип позже, чтобы выяснить тип, необходимый ранее.
    2019-05-03 11: 25: 35Z
.toSet
источник размещен Вот