Есть ли что-то вроде функции «возможно» Хаскелла, встроенной в Scala? - PullRequest
14 голосов
/ 07 августа 2009

То, что я ищу, это эта функция:

def maybe[A, B](a: Option[A])(f: A => B)(g: () => B): B = a match 
{
    case Some(x) => f(x)
    case None => g()
}

Это в прелюдии на Haskell, поэтому я думаю, что это может быть где-то в стандартной библиотеке Scala, и я просто пропустил это. Я ненавижу перекодировать его в проектах, поэтому мне интересно, знает ли кто-нибудь, где он находится, или его там точно нет. Или есть лучший способ получить эту функциональность?

Ответы [ 7 ]

16 голосов
/ 07 августа 2009

Другие ответы дали композицию map + getOrElse. Просто для записи, вы можете «добавить» функцию maybe к Option следующим образом:

implicit def optionWithMaybe[A](opt: Option[A]) = new {
  def maybe[B](f: A=>B)(g: =>B) = opt map f getOrElse g
}

Стоит отметить, что синтаксис функций высшего порядка в Scala обычно лучше, когда параметр функции стоит последним. Таким образом, лучший способ организовать maybe будет выглядеть следующим образом:

def maybe[B](g: =>B)(f: A=>B) = opt map f getOrElse g

Это можно использовать следующим образом:

val opt: Option[String] = ...
opt.maybe("") { _.toUpperCase }
14 голосов
/ 07 августа 2009

Вы могли бы сделать

val opt:Option[A] = // ...
val result:B = opt.map(f).getOrElse(g());

getOrElse принимает параметр по имени, поэтому g будет оцениваться, только если opt равно None.

4 голосов
/ 22 мая 2012

Вы можете использовать scalaz, а затем у вас есть неявное преобразование в OptionW, которое имеет fold, или вы можете использовать Scala 2.10.0-M3 и использовать встроенный Option.fold

scala> Some(1).fold(5)(_ * 2)
res5: Int = 2

scala> (None: Option[Int]).fold(5)(_ * 2)
res7: Int = 5

Обратите внимание, что сигнатура сгиба скаляза равна fold[X](some: A => X, none: => X), а встроенная версия выглядит как fold[X](none: => X)(some: A => X).

4 голосов
/ 08 августа 2009

Метод будет называться кратным, если он будет придерживаться соглашения (см. Either.fold, который является катаморфизмом для обоих).

0 голосов
/ 11 августа 2014

Я бы использовал B)(f:A=>B):B" rel="nofollow">Option.fold для этого:

opt.fold(g)(f)

Обратите внимание, что g - это имя, как и getOrElse. Также обратите внимание на инверсию случаев.

0 голосов
/ 07 августа 2009

Я не думаю, что есть. Тем не менее, я бы написал, чтобы взять g по имени:

def maybe[A, B](a: Option[A])(f: A => B)(g: => B): B = a.map(f).getOrElse(g)

Это более похоже на Scala- и Haskell и немного приятнее в использовании.

0 голосов
/ 07 августа 2009

Я не думаю, что есть. Лучшее, что я могу придумать, - это связать "map" и "getOrElse" в Option:

scala> var a: Option[String] = Some("hello")
a: Option[String] = Some(hello)

scala> a.map(_.toUpperCase).getOrElse("empty") 
res19: java.lang.String = HELLO

scala> a = None
a: Option[String] = None

scala> a.map(_.toUpperCase).getOrElse("empty")
res21: java.lang.String = empty
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...