Подтвердить что ты не робот

Почему опция не имеет метод сгиба?

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

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

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

map(ifSome).getOrElse(ifNone)

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

4b9b3361

Ответ 1

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

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

или

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

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

Edit:

Но то, что вы действительно хотите, это Scalazs catamorphism cata (в основном a 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, когда это "более естественный способ выразить это". Существует много случаев, когда достаточно простого map - getOrElse, особенно когда оно связано с потенциальной цепью партий map s. (Хотя вы могли бы также цепью fun с составом функций, конечно же - это зависит от того, хотите ли вы сосредоточиться на композиции функции или преобразовании значения.)

Ответ 2

Я лично нахожу такие методы, как 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
}

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

Ответ 3

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

Ответ 4

Как упоминалось Debilski, вы можете использовать Scalaz 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 }

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