2009-08-07 20 views
14

Lo que estoy buscando es esta función:¿Hay algo como la función de "tal vez" de Haskell incorporada en Scala?

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

Está en el preludio Haskell, así que estoy pensando que podría ser en la biblioteca estándar Scala en alguna parte y yo sólo he echado de ella. Odio tener que recodificarlo en proyectos, así que me pregunto si alguien sabe dónde está, o si definitivamente no está allí. ¿O hay un método mejor para obtener esta funcionalidad?

Respuesta

14

Usted podría hacer

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

getOrElse toma un parámetro por nombre, por lo g solamente se evaluará si es optNone.

+4

¿Por qué 'a => f (a)' en lugar de solo 'f'? –

+1

Bueno, en realidad, simplemente debería funcionar. –

0

No creo que exista. Lo mejor que podía llegar a es de cadena Opción "mapa" y "getOrElse" juntos:

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 
0

No creo que hay. Sin embargo, me gustaría escribir para tomar g por su nombre:

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

Esto es más Scala- y Haskell-like y un poco más agradable de usar.

16

Otras respuestas dan la composición map + getOrElse. Sólo para que conste, se puede "añadir" una función maybe-Option de la siguiente manera:

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

Vale la pena señalar que la sintaxis de las funciones de orden superior en Scala es generalmente mejor cuando el parámetro de la función viene al final. Por lo tanto, una mejor manera de organizar maybe sería la siguiente:

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

Esto podría ser utilizado de la siguiente manera:

val opt: Option[String] = ... 
opt.maybe("") { _.toUpperCase } 
4

El método se llama pliegue si se tratara de adherirse a la Convención (véase De cualquier .fold que es el catamorfismo para O bien).

4

Puede utilizar scalaz, y entonces usted tiene una conversión implícita a OptionWfold que tiene, o puede utilizar Scala 2.10.0-M3 y usar la orden interna Option.fold

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

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

Tenga en cuenta que la firma pliegue scalaz es fold[X](some: A => X, none: => X), mientras que el builtin parece ser fold[X](none: => X)(some: A => X).

+0

+1 por mencionar que la función ya está en la biblioteca estándar en la última versión – gerferra

0

que haría uso de este Option.fold:

opt.fold(g)(f) 

Tenga en cuenta que es g por nombre, al igual que getOrElse. También tenga en cuenta la inversión de los casos.

Cuestiones relacionadas