I want to be able to apply an operation f: (T,T) => T
to Option[T]
values in Scala. I want the result to be None
if any of the two values is None
.
More specifically, I want to know if is there a shorter way to do the following:
def opt_apply[T](f: (T,T) => V, x: Option[T], y: Option[T]): Option[T] = {
(x,y) match {
case (Some(u),Some(v)) => Some(f(u,v))
case _ => None
}
}
I have tryied (x zip y) map {case (u,v) => f(u,v)}
but the result is an Iterator[T]
not an Option[T]
.
Any help will be appreciated. Thanks.
I have a slightly older version of scalaz than retronym but the following works for me as an example and is generalizable for the case where you have 3 types
T, U, V
and not just one:I can then add:
a.zip(b)
does result in an Iterable[(A, B)] (with, because it's from Options, at most one element).headOption
then returns the first element as an Option.You can use for comprehensions:
Which is sugar for:
This is also possible due to Option being a Monad
@RahulG's answer exploits the fact that
Option
is a monad (even though there is no type to represent this in the Scala library). The compiler expands thefor
comprehension to the following:You can also treat it as an applicative functor, with some help from Scalaz:
A key difference is that in the monadic calculation, a failure (that is,
None
) of calculationa
short circuits the evaluation. In the applicative style, botha
andb
are evaluated, and if both areSome
s, the pure function is called. You can also see that in the monadic calculation, the valueaa
could have been used in the calculationb
; in the applicative version,b
cannot depend on the result ofa
.