2009-08-07 17 views
14

Quello che sto cercando è questa funzione:Esiste qualcosa come la funzione 'forse' di Haskell incorporata in Scala?

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

E 'nel preludio Haskell così sto pensando che potrebbe essere nella libreria standard Scala da qualche parte e ho appena perso. Odio doverlo ricodificare nei progetti, quindi mi chiedo se qualcuno sa dove sia o se non ci sia definitivamente. O c'è un metodo migliore per ottenere questa funzionalità?

risposta

14

Si potrebbe fare

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

getOrElse prende un parametro per nome, quindi sarà tenuto conto soltanto g se opt è None.

+4

Perché 'a => f (a)' invece di solo 'f'? –

+1

Beh, in realtà, dovrebbe funzionare. –

0

Non penso ci sia. Il meglio che ho potuto venire in mente è a catena Option "mappa" e "getOrElse" insieme:

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

Non credo che ci sia. Tuttavia, mi piacerebbe scrivere per scattare g per nome:

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

Questo è più Scala- e Haskell-like e un po 'più bello da usare.

16

Altre risposte hanno dato la composizione map + getOrElse. Solo per la cronaca, si può "aggiungere" una funzione maybe-Option nel seguente modo:

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

Vale la pena notare che la sintassi delle funzioni di ordine superiore a Scala di solito è più bello quando il parametro della funzione viene per ultimo. Pertanto, un modo migliore per organizzare maybe potrebbe essere il seguente:

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

Questo potrebbe essere utilizzato come segue:

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

Il metodo verrà chiamato piega se dovesse aderire alla convenzione (vedere né .fold che è il catamorfismo per entrambi).

4

È possibile utilizzare scalaz, e poi ci sono una conversione implicita per OptionW che ha fold, oppure è possibile utilizzare Scala 2.10.0-M3 e utilizzare la funzione interna Option.fold

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

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

Si noti che lo scalaz piega firma è fold[X](some: A => X, none: => X), mentre il builtin sembra essere fold[X](none: => X)(some: A => X).

+0

+1 per aver menzionato che la funzione è già nella libreria standard nell'ultima versione – gerferra

0

userei Option.fold per questo:

opt.fold(g)(f) 

noti che g è per nome, proprio come getOrElse. Notare anche l'inversione dei casi.

Problemi correlati