Вопрос

интересно, почему scala.Option нет метода fold Как это определено:

fold(ifSome: A => B , ifNone: => B)

эквивалентно

map(ifSome).getOrElse(ifNone)

Нет ли не лучше, чем использовать map + getOrElse?

Это было полезно?

Решение

Ты можешь сделать:

opt foldLeft (els) ((x, y) => fun(x))

или же

(els /: opt) ((x,y) => fun(x))

(Оба решения оценят els по цене, что может быть не то, что вы хотите. Благодаря Рекс Керр для указания на это.)

Редактировать:

Но вы действительно хотите Катаморфизм cata (в основном а fold который не только обрабатывает Some ценность, но также отображает None часть, что вы описали)

opt.cata(fun, els)

определяется как (где value Значение опции удвалена)

def cata[X](some: A => X, none: => X): X = value match {
  case None => none
  case Some(a) => some(a)
}

что эквивалентно opt.map(some).getOrElse(none).

Хотя я должен отметить, что вы должны использовать CATA только тогда, когда это «более естественный» способ выразить его. Есть много случаев, когда простые mapgetOrElse достаточно, особенно когда это включает в себя потенциально цепочку mapс (Хотя вы также можете цепорить funS с функциональной составой, конечно, это зависит от того, хотите ли вы сосредоточиться на составе функции или преобразовании значений.)

Другие советы

Я лично нахожу такие методы, как cata Это занимает два закрытия, поскольку аргументы часто переусердствуют. Вы действительно получаете читаемость за map + getOrElse? Подумайте о новичке в вашем коде: что они сделают из

opt cata { x => x + 1, 0 }

Вы действительно думаете, что это яснее, чем

opt map { x => x + 1 } getOrElse 0

На самом деле я бы сказал, что ни один из них не предпочтительнее старого старого

opt match {
  case Some(x) => x + 1
  case None => 0
}

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

Это было наконец добавлено в Scala 2.10, с подписью fold[B](ifEmpty: => B)(f: A => B): B.

К сожалению, это имеет общее негативное последствие: B выведен для вызовов, основанных только на ifEmpty Аргумент, который на практике часто более узкий. Например (правильная версия уже находится в стандартной библиотеке, это просто для демонстрации)

 def toList[A](x: Option[A]) = x.fold(Nil)(_ :: Nil)

Скала сделает вывод B быть Nil.type вместо желаемого List[A] и жаловаться на f не возвращается Nil.type. Анкет Вместо этого вам нужен один из

 x.fold[List[A]](Nil)(_ :: Nil)
 x.fold(Nil: List[A])(_ :: Nil)

Это делает fold не совсем эквивалентно соответствующим match.

Как упомянуто Debilski, вы можете использовать Скалаз OptionW.cata или же fold. Анкет Как прокомментировал Джейсон, названные параметры делают это красивым:

opt.fold { ifSome = _ + 1, ifNone = 0 }

Теперь, если значение, которое вы хотите в None случай mzero для некоторых Monoid[M] и у вас есть функция f: A => M для Some Случай, вы можете сделать это:

opt foldMap f

Так,

opt map (_ + 1) getOrElse 0

становится

opt foldMap (_ + 1)

Лично я считаю Option должен иметь apply Метод, который был бы катаморфизмом. Таким образом, вы могли бы просто сделать это:

opt { _ + 1, 0 }

или же

opt { some = _ + 1, none = 0 }

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top