Тип несоответствия с картой и плоской картой

При попытке играть с опциями в scala я столкнулся с этой своеобразной проблемой.

Я начал с создания List [Option [Int]] следующим образом:

scala> List(Some(1),Some(2),None,Some(3))
res0: List[Option[Int]] = List(Some(1), Some(2), None, Some(3))

Затем я попытался отобразить дополнение к 1 над записями списка в res0 следующим образом:

scala> res0 map (_ + 1)

Это дало мне ошибку:

:9: error: type mismatch;
 found   : Int(1)
 required: String
              res0 map (_ + 1)
                            ^

Затем я попробовал flatMapping дополнение по элементам следующим образом:

scala> res0 flatMap (_ + 1)

Это дало мне ту же ошибку:

:9: error: type mismatch;
 found   : Int(1)
 required: String
              res0 flatMap (_ + 1)
                                ^

But something like res0.flatMap(r => r) works just fine with a result of:

res9: List[Int] = List(1, 2, 3)

Может ли кто-нибудь сказать мне, почему добавление записи в 1 не получится для карты и flatMap?

1

6 ответы

Первые две вещи, которые вы пробовали, не удалось, потому что вы пытаетесь добавить Option в Int , и это невозможно.

Странное сообщение об ошибке происходит из-за того, что Scala предполагает, поскольку Option не имеет метода + , который вы пытаетесь конкатенации String d необходимо либо добавить Option в String , либо String в Option ), и вы делаете ни, следовательно, сообщение об ошибке.

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

6
добавлено
Я думаю, что sc_ray также запутался, потому что при попытке res0 flatMap (_ + 1) он, вероятно, думал, что он эквивалентен res0.flatten.map (_ + 1) (который очевидно, что он пытался сделать), в то время как на самом деле это эквивалентно res0.map (_ + 1) .flatten . Возможно, flatMap должен был называться mapFlat вместо flatMap :-)
добавлено автор Régis Jean-Gilles, источник

Чтобы увеличить все значения, которые не являются None , вам необходимо также отобразить каждый элемент Option в списке:

scala> res0.map(_.map(_ + 1))
res1: List[Option[Int]] = List(Some(2), Some(3), None, Some(4))

Если вы хотите отфильтровать None s, вы действительно используете flatMap :

scala> res0.flatMap(_.map(_ + 1))
res2: List[Int] = List(2, 3, 4)
1
добавлено

Обе функции, заданные flatMap , а также функция, заданная для map , принимают значение типа элемента списка - в этом случае Option [Int] . Но ваша функция _ + 1 ожидает Int , а не Option [Int] , поэтому вы не можете использовать ее в качестве аргумента для map или flatMap в этом случае. Далее функция, заданная flatMap , должна возвращать итерабельную¹, но ваша функция вернет число.

Это сделает то, что вы хотите: res0 flatMap (_ map (_ + 1)) . Здесь функция flatMap принимает Option [Int] и возвращает Option [Int] , вызывая map по выбору. flatMap , затем принимает параметры, возвращаемые функцией, и объединяет их.

¹ Технически GenTraversableOnce .

1
добавлено

Вы пытаетесь вызвать e. + (1) для каждого элемента e в List [Option [Int]] , но + не является функцией, объявленной Option [_] . Однако конкатенация строк возможна (я предполагаю, что существует неявный из Any в String ), но только если второй аргумент также был строкой (не уверен, почему неявный, существование которого я предполагал, здесь не рассматривается).

Вы можете решить эту проблему, выполнив значение по умолчанию, предложенное @korefn, или «спрячьте» различие между Some (x) и None в другом вызове < code> map , а именно:

map(_.map(_ + 1))
1
добавлено

Попробуйте использовать get для извлечения значения из Some [Int] в Int , позволяющего вычислять значение + 1 , то есть:

res0 map{_.getOrElse(0) + 1}

As pointed out by @Sepp2k you could alternatively use a collect to avoid having a default for None

res0 collect {case Some(x) => x + 1 }
1
добавлено
Я не думаю, что OP хочет обрабатывать None s как 0. По крайней мере, он ничего не сказал, чтобы предположить это.
добавлено автор sepp2k, источник
Две вещи не могут быть альтернативой друг другу, если они производят разные результаты.
добавлено автор sepp2k, источник
Это делается для того, чтобы избежать NoSuchElementException при вызове get на None полезной альтернативой было бы использование collect, чтобы этого избежать.
добавлено автор korefn, источник
В этом случае это поможет распаковать Some (x) в x , и это хорошо выглядит для моих глаз (мне нравится синтаксис).
добавлено автор korefn, источник

Они терпят неудачу, потому что типы ошибочны, и компилятор правильно заявляет об этом как таковой.

The map case fails because map expects a function A => B. In your code, A => B is really Int => Int which will not work because calling map on your list means that A is actually Option[Int].

Furthermore, flatMap expects a function of the form A => F[B]. So you will get your answer if you did res0 flatMap { o => o map { a => a + 1 } }. This basically is the expansion of:

for {
  element <- res0//o above
  value <- element//a above
} yield value + 1
1
добавлено
pro.jvm
pro.jvm
3 503 участник(ов)

Сообщество разработчиков Java Scala Kotlin Groovy Clojure Чат для нач-их: @javastart Наш сайт: projvm.com projvm.ru Наш канал: @proJVM Вакансии: @jvmjobs Конфы: @jvmconf

Scala User Group
Scala User Group
1 486 участник(ов)

[RU] Scala Chat. Rules, additional links, FAQ: https://telegra.ph/Russian-Speaking-Scala-User-Group-08-27

Scala Jobs
Scala Jobs
852 участник(ов)

Rules: http://telegra.ph/My-lyudi-i-ehto-znachit-chto-nam-nuzhna-organizaciya-02-07 Main Scala Channel: https://t.me/scala_jobs_feed Flood Room: https://t.me/scala_ponv