Let's say I have two optional Ints (both can be Some or None):
val one : Option[Int] = Some(1)
val two : Option[Int] = Some(2)
My question is the following: Are there any intelligent way to sum them op using Scalas brilliant collection-methods? I realize that I could merge them into a collection, flatten it and use reduceLeftOption like so:
(one :: two :: Nil).flatten.reduceLeftOption(_ + _) // Some(3)
But, the solution above means creating a new collection, and living in a rich and developed world that takes time from all the other first world activities I might immerse myself into. And in a world where programming gets more and more luxurious for programmers like us, there must be one or more luxurious first world answer(s) to this, right?
Edit: So to spell things out, here are some examples:
If one = Some(1) and two = Some(2) we should have Some(3)
If one = Some(1) and two = None we should have Some(1)
If one = None and two = Some(2) we should have Some(2)
If both one and two are None we should have None, since neither one or two can be summed correctly.
Hope that clarified things :-)
for (x <-one; y <- two) yield x+y
Or the less readable but strictly equivalent:
one.flatMap{x=>two.map(x+_)}
UPDATE: As your latest edit made quite clear, you only want a None as the result when both the input options are None. In this case I don't think you'll get anything better in terms of simplicity than what you already use. I could shorten it a bit but overall this is just the same:
(one ++ two).reduceOption(_ + _)
obligatory scalaz answer is to use the scalaz Option monoid:
scala> one |+| two
res0: Option[Int] = Some(3)
It will do what you want with respect to None:
scala> two |+| None
res1: Option[Int] = Some(2)
scala> none[Int] |+| none[Int]
res2: Option[Int] = None
That none method is a method from scalaz which helps with type inference because instead of returning None <: Option[Nothing] it returns a Option[Int], there is a similar method from Some which returns an Option[A] for any given A instead of a Some[A]:
scala> 1.some |+| 2.some
res3: Option[Int] = Some(3)
How about:
one.map(_ + two.getOrElse(0)).orElse(two)
You could try this:
for( x <- one.orElse(Some(0)); y <- two.orElse(Some(0))) yield x+y
Related
When I have one Option[T] instance it is quite easy to perform any operation on T using monadic operations such as map() and flatMap(). This way I don't have to do checks to see whether it is defined or empty, and chain operations together to ultimately get an Option[R] for the result R.
My difficulty is whether there is a similar elegant way to perform functions on two Option[T] instances.
Lets take a simple example where I have two vals, x and y of type Option[Int]. And I want to get the maximum of them if they are both defined, or the one that is defined if only one is defined, and None if none are defined.
How would one write this elegantly without involving lots of isDefined checks inside the map() of the first Option?
You can use something like this:
def optMax(op1:Option[Int], op2: Option[Int]) = op1 ++ op2 match {
case Nil => None
case list => list.max
}
Or one much better:
def f(vars: Option[Int]*) = (for( vs <- vars) yield vs).max
#jwvh,thanks for a good improvement:
def f(vars: Option[Int]*) = vars.max
Usually, you'll want to do something if both values are defined.
In that case, you could use a for-comprehension:
val aOpt: Option[Int] = getIntOpt
val bOpt: Option[Int] = getIntOpt
val maxOpt: Option[Int] =
for {
a <- aOpt
b <- bOpt
} yield max(a, b)
Now, the problem you described is not as common. You want to do something if both values are defined, but you also want to retrieve the value of an option if only one of them is defined.
I would just use the for-comprehension above, and then chain two calls to orElse to provide alternative values if maxOpt turns out to be None.
maxOpt orElse aOpt orElse bOpt
orElse's signature:
def orElse[B >: A](alternative: ⇒ Option[B]): Option[B]
Here's another fwiw:
import scala.util.Try
def maxOpt (a:Option[Int]*)= Try(a.flatten.max).toOption
It works with n arguments (including zero arguments).
Pattern matching would allow something easy to grasp, but that might not be the most elegant way:
def maxOpt[T](optA: Option[T], optB: Option[T])(implicit f: (T, T) => T): Option[T] = (optA, optB) match {
case (Some(a), Some(b)) => Some(f(a, b))
case (None, Some(b)) => Some(b)
case (Some(a), None) => Some(a)
case (None, None) => None
}
You end up with something like:
scala> maxOpt(Some(1), None)(Math.max)
res2: Option[Int] = Some(1)
Once you have that building, block, you can use it inside for-comp or monadic operations.
To get maxOpt, you can also use an applicative, which using Scalaz would look like (aOpt |#| bOpt) { max(_, _) } & then chain orElses as #dcastro suggested.
I assume you expect Some[Int]|None as a result, not Int|None (otherwise return type has to be Any):
def maxOption(opts: Option[Int]*) = {
val flattened = opts.flatten
flattened.headOption.map { _ => flattened.max }
}
Actually, Scala already gives you this ability more or less directly.
scala> import Ordering.Implicits._
import Ordering.Implicits._
scala> val (a,b,n:Option[Int]) = (Option(4), Option(9), None)
a: Option[Int] = Some(4)
b: Option[Int] = Some(9)
n: Option[Int] = None
scala> a max b
res60: Option[Int] = Some(9)
scala> a max n
res61: Option[Int] = Some(4)
scala> n max b
res62: Option[Int] = Some(9)
scala> n max n
res63: Option[Int] = None
A Haskell-ish take on this question is to observe that the following operations:
max, min :: Ord a => a -> a -> a
max a b = if a < b then b else a
min a b = if a < b then a else b
...are associative:
max a (max b c) == max (max a b) c
min a (min b c) == min (min a b) c
As such, any type Ord a => a together with either of these operations is a semigroup, a concept for which reusable abstractions can be built.
And you're dealing with Maybe (Haskell for "option"), which adds a generic "neutral" element to the base a type (you want max Nothing x == x to hold as a law). This takes you into monoids, which are a subtype of semigroups.
The Haskell semigroups library provides a Semigroup type class and two wrapper types, Max and Min, that generically implement the corresponding behaviors.
Since we're dealing with Maybe, in terms of that library the type that captures the semantics you want is Option (Max a)—a monoid that has the same binary operation as the Max semigroup, and uses Nothing as the identity element. So then the function simply becomes:
maxOpt :: Ord a => Option (Max a) -> Option (Max a) -> Option (Max a)
maxOpt a b = a <> b
...which since it's just the <> operator for Option (Max a) is not worth writing. You also gain all the other utility functions and classes that work on Semigroup and Monoid, so for example to find the maximum element of a [Option (Max a)] you'd just use the mconcat function.
The scalaz library comes with a Semigroup and a Monoid trait, as well as Max, Min, MaxVal and MinVal tags that implement those traits, so in fact the stuff that I've demonstrated here in Haskell exists in scalaz as well.
Jordan West in this presentation from Scalamachine clearly speaks about map2 function. Turns out the function was available in Scalaz 6 but I can't find it or any equivalent in Scalaz 7.
E.g. I would like to be able to run this code:
List(Some(1), Some(2)).map2(_ + 1)
and get as a result
List(Some(2), Some(3))
Where can I find this function in Scalaz 7?
EDIT:
Ideally, I would like to be able to execute any function f: A => B on l: List[Option[A]]
l.map2(f)
And get List[Option[B]] with the intuitive semantics.
You can use the applicative syntax instead:
scala> List(Some(1), Some(2)) <*> List((x:Option[Int]) => x |+| Some(1))
res0: List[Option[Int]] = List(Some(2), Some(3))
Scalaz 7 is a different beast compared to Scalaz 6.
I haven't found map2 in scalaz 7 and the applicative approach by #I.K. is the most similar I could think. However in this situation where the "shape of the list" doesn't change, I would map and mappend:
List(1.some, 2.some) map (_ |+| 1.some)
res: List[Option[Int]] = List(Some(2), Some(3))
Of course if the default operation assigned to the type is not the desired one, then I would use an exiting Tag from scalaz or a custom implicit.
EDIT
I have just noticed your answer: the other-way-round expected result could be achieved using traverse
List(1.some, 2.some, 3.some) traverseU (_ |+| 1.some)
Some(List(2, 3, 4))
Ok, there does not seem to exist such function in Scalaz 7 but there is a nice way around using Monad Transformers:
OptionT[List, Int](List(Some(1), Some(2))).map(_ + 1).run
// List(Some(2), Some(3))
or in the case of l: List[Option[A]]
OptionT[List, A](l).map(f).run
I am trying to solve a "simple" exercise in Scala. I have this function:
def mean(xs: Seq[Double]): Option[Double] =
if (xs.isEmpty) None
else Some(xs.sum / xs.length)
This is the text of the exercise:
EXERCISE 2: Implement the variance function (if the mean is m ,
variance is the mean of math.pow(x - m, 2) , see definition ) in terms
of mean and flatMap .
I was thinking something like
val xs = List(1.3,2.1,3.2)
val m = mean(xs)
xs flatMap(x=> math.pow(x-m,2)).mean //error!
What is the right way to solve? If possible I would like also a small theoretical explanation
I wouldn't call this simple.
map on Option[A] takes a function A => B and returns an Option[B] which is a Some if the original was a Some, and None otherwise. So Some(2).map(_+2) gives Some(4), but None[Int].map(_+2) gives None.
flatMap is much the same, but it takes a function A => Option[B] and still returns an Option[B]. If the original is None or the given function results in None, the result is None otherwise it's a Some[B].
You don't want to flatMap over the list, you want to flatMap the option. I'll give you a hint, it starts with:
mean(xs).flatMap(m => ...
After that arrow, m is a Double, not an Option[Double].
Edit:
Alright, fine, since we're getting all downvotey and not being helpful, here's the full answer:
def variance(xs: Seq[Double]): Option[Double] = {
mean(xs).flatMap(m => mean(xs.map(x => Math.pow(x-m, 2))))
}
Matt Putnam's answer gives some good pointers. I found it easier to understand this problem by breaking it up into smaller chunks.
scala> val xs = List(1.3,2.1,3.2)
xs: List[Double] = List(1.3, 2.1, 3.2)
scala> def mean(xs: Seq[Double]): Option[Double] = {
| if (xs.isEmpty) None
| else Some(xs.sum / xs.length)
| }
mean: (xs: Seq[Double])Option[Double]
Calculate the deviation of each element from the mean of the sequence:
scala> mean(xs).map(m => xs.map(x => x-m))
res0: Option[List[Double]] = Some(List(-0.9000000000000001, -0.10000000000000009, 1.0))
map works because if mean(xs) is Some, x => x-m is evaluated. Otherwise it isn't and we get None.
Now calculate the squared deviation from the mean of the sequence:
scala> mean(xs).map(m => xs.map(x => math.pow(x-m, 2)))
res1: Option[List[Double]] = Some(List(0.8100000000000003, 0.010000000000000018, 1.0))
Then calculate the mean of that:
scala> mean(xs).map(m => mean(xs.map(x => math.pow(x-m, 2))))
res2: Option[Option[Double]] = Some(Some(0.6066666666666668))
But here we have an Option that contains an Option, so we use flatMap to get the value of the first Some. So the solution with the desired return type Option[Double] is:
scala> mean(xs).flatMap(m => mean(xs.map(x => math.pow(x-m, 2))))
res3: Option[Double] = Some(0.6066666666666668)
I'm finding that I often have to chain together functions that work on an Option and return a different Option that look something like this:
if(foo.isDefined) someFunctionReturningOption(foo.get) else None
Is there a cleaner way to do this? This pattern gets quite verbose with more complicated variables.
I'm seeing it a fair bit in form handling code that has to deal with optional data. It'll insert None if the value is None or some transformation (which could potentially fail) if there is some value.
This is very much like the ?. operator proposed for C#.
You can use flatMap:
foo.flatMap(someFunctionReturningOption(_))
Or in a for-comprehension:
for {
f <- foo
r <- someFunctionReturningOption(f)
} yield r
The for-comprehension is preferred when chaining multiple instances of these functions together, as they de-sugar to flatMaps.
There're a lot of options (pun intended) but for comprehensions, I guess, is the most convinient in case of chains
for {
x <- xOpt
y <- someFunctionReturningOption(x)
z <- anotherFunctionReturningOption(y)
} yield z
You're looking for flatMap:
foo.flatMap(someFunctionReturningOption)
This fits into the general monadic structure, where a monad wrapping a type uses flatMap to return the same type (e.g. flatMap on Seq[T] returns a Seq).
Option supports map() so when x is an Option[Int] this construct:
if (x.isDefined)
"number %d".format(x.get)
else
None
is easier to write as:
x map (i => "number %d".format(i))
map will keep None unmodified, but it will apply the function you pass to it to any value, and wrap the result back into an Option. For example note how 'x' gets converted to a string message below, but 'y' gets passed along as None:
scala> val x: Option[Int] = Some(3)
x: Option[Int] = Some(3)
scala> val y: Option[Int] = None
y: Option[Int] = None
scala> x map (i => "number %d".format(i))
res0: Option[String] = Some(number 3)
scala> y map (i => "number %d".format(i))
res1: Option[String] = None
I found a piece of code I wrote some time ago using _* to create a flattened set from a list of objects.
The real line of code is a bit more complex and as I didn't remember exactly why was that there, took a bit of experimentation to understand the effect, which is actually very simple as seen in the following REPL session:
scala> val someList = List("a","a","b")
someList: List[java.lang.String] = List(a, a, b)
scala> val x = Set(someList: _*)
x: scala.collection.immutable.Set[java.lang.String] = Set(a, b)
scala> val y = Set(someList).flatten
y: scala.collection.immutable.Set[java.lang.String] = Set(a, b)
scala> x == y
res0: Boolean = true
Just as a reference of what happens without flatten:
scala> val z = Set(someList)
z: scala.collection.immutable.Set[List[java.lang.String]] = Set(List(a, a, b))
As I can't remember where did I get that idiom from I'd like to hear about what is actually happening there and if there is any consequence in going for one way or the other (besides the readability impact)
P.S.: Maybe as an effect of the overuse of underscore in Scala language (IMHO), it is kind of difficult to find documentation about some of its use cases, specially if it comes together with a symbol commonly used as a wildcard in most search engines.
_* is for expand this collection as if it was written here literally, so
val x = Set(Seq(1,2,3,4): _*)
is the same as
val x = Set(1,2,3,4)
Whereas, Set(someList) treats someList as a single argument.
To lookup funky symbols, you could use symbolhound