#scala #join #option #monads #flatten
#scala #монады #сгладить #scala-опция
Вопрос:
Допустим, у меня есть val s: Option[Option[String]]
. Таким образом, она может иметь следующие значения:
Some(Some("foo"))
Some(None)
None
Я хочу уменьшить ее так, чтобы первая стала Some("foo")
, а две другие стали None
. Очевидно, что есть много способов добиться этого, но я ищу простой, возможно, встроенный, менее чем однострочный.
Ответ №1:
Жаль, что flatten
этого не существует. Так и должно быть.
Flatten теперь существует.
Как и раньше,
s getOrElse None
(в дополнение к другим ответам) также сделает то же самое.
Комментарии:
1. похоже, что она существует сейчас: scala> Some(Некоторые(1)).сгладить res10: Option[Int] = Some(1)
2. похоже, flatten также внедрил ее в cats
3. @Alexy когда я вызываю
flatten
такой объект, какSome(Some(Some(1)))
, я получаюCannot prove that Any <:< Option[B]
Ответ №2:
Вы могли бы использовать для этого scalaz join
, поскольку это одна из монадических операций:
doubleOpt.join
Вот это в REPL:
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> some(some("X")).join
res0: Option[java.lang.String] = Some(X)
scala> some(none[String]).join
res1: Option[String] = None
scala> none[Option[String]].join
res3: Option[String] = None
Он доступен для всего, что имеет экземпляр typeclass для монады.
Комментарии:
1. У меня есть такая карта,
val map = Map("a"->Some(Some(1)), "b"->2)
когда я вызываюmap.get("a").join
, я вижуcould not find implicit value for parameter ev: scalaz.Liskov.<~<[Any,Option[B]]
Ответ №3:
s.flatten
за которым следует набор символов, чтобы довести меня до минимума, который позволяет stackoverflow
Комментарии:
1. Это то, о чем я думаю, но это возвращает Iterable, а не Option.
2. Хм, это очень странно. Зачем им это делать? Вместо этого попробуйте s.flatmap(x=>x).
3. Можно было бы также написать
s flatMap identity
.4. Подводя итог вышесказанному:
List(Some(Some("foo")), Some(None), None) map { _ flatMap identity }
даетList[Option[java.lang.String]] = List(Some(foo), None, None)
результат, который, я думаю, и есть то, чего хотел Кнут (OP и первый неполярный медвежонок по имени «Кнут», о котором я слышал).
Ответ №4:
Я думаю, что преобразование в Iterable просто отлично. Используйте эти шаги, чтобы перейти от Option[Option[String]
к одному Option[String]
s.flatten.headOption
(который возвращает Option[String]
)
Ответ №5:
Вы могли бы использовать flatMap следующим образом:
val options = List(Some(Some(1)), Some(None), None)
options map (_ flatMap (a => a))
Это приведет к сопоставлению List[Option[Option[Int]]]
с List[Option[Int]]
.
Если у вас просто есть опция, вы можете использовать ее следующим образом:
val option = Some(Some(2))
val unzippedOption = option flatMap (b => b)
Это приведет к выравниванию вашего Option[Option[Int]]
до Option[Int]
.
Ответ №6:
Ну, я на самом деле не понимаю, почему это может быть просто None (третий случай). Если это действительно может быть также просто None, то я бы проголосовал за ответ Рекса Керра, иначе было бы достаточно just .get:
scala> Some(Some("foo")).get
res0: Some[java.lang.String] = Some(foo)
scala> Some(None).get
res1: None.type = None
Комментарии:
1. Это может быть,
None
потому что этоOption
!2. Да, но это опция внутри опции … поэтому я бы ожидал, что это Some (Некоторое («что-то»)) для положительного результата и Some (None) для отрицательного результата. Тогда какое третье состояние описывает просто None? Что ж, если проблема заключается в логике трех состояний, только тогда это имеет смысл.
3. Это своего рода эквивалент future:
Some(Some(X))
является вычисляемым значением,Some(None)
указывает, что future завершилось без значения, иNone
указывает, что future не вернулся4. Опция [Строка] является строкой или нет. Давайте запишем это как String 1, что означает, что это может быть любая строка или 1 другая вещь. Тогда параметр [Option[String]] равен (Строка 1) 1 или Строка 2. То есть это строка, или это одна из двух других вещей. Другими словами, параметр[Option[Строка]] изоморфен любому[логическое значение, строка]. Я думаю, что более поздняя структура более четко указывает на то, что либо вычисление успешно приводит к созданию строки, либо может произойти сбой двумя разными способами.
5. Хе-хе, хорошее объяснение — «Есть много способов потерпеть неудачу, но только один для достижения успеха». 🙂