In scala, how do I define addition over two Option arguments? Just to be specific, let's say they're wrappers for Int
types (I'm actually working with maps of doubles but this example is simpler).
I tried the following but it just gives me an error:
def addOpt(a:Option[Int], b:Option[Int]) = {
a match {
case Some(x) => x.get
case None => 0
} + b match {
case Some(y) => y.get
case None => 0
}
}
Edited to add:
In my actual problem, I'm adding two maps which are standins for sparse vectors. So the None case returns Map[Int, Double] and the + is actually a ++ (with the tweak at stackoverflow.com/a/7080321/614684)
You might find life becomes a lot easier when you realize that you can stand on the shoulders of giants and take advantage of common abstractions and the libraries built to use them. To this end, this question is basically about dealing with monoids (see related questions below for more about this) and the library in question is called scalaz.
Using scalaz FP, this is just:
def add(a: Option[Int], b: Option[Int]) = ~(a |+| b)
What is more this works on any monoid M:
def add[M: Monoid](a: Option[M], b: Option[M]) = ~(a |+| b)
Even more usefully, it works on any number of them placed inside a Foldable
container:
def add[M: Monoid, F: Foldable](as: F[Option[M]]) = ~as.asMA.sum
Note that some rather useful monoids, aside from the obvious Int
, String
, Boolean
are:
Map[A, B: Monoid]
A => (B: Monoid)
Option[A: Monoid]
In fact, it's barely worth the bother of extracting your own method:
scala> some(some(some(1))) #:: some(some(some(2))) #:: Stream.empty
res0: scala.collection.immutable.Stream[Option[Option[Option[Int]]]] = Stream(Some(Some(Some(1))), ?)
scala> ~res0.asMA.sum
res1: Option[Option[Int]] = Some(Some(3))
Q. What is a monoid?
A monoid is a type
M
for which there exists an associative binary operation(M, M) => M
and an identityI
under this operation, such thatmplus(m, I) == m == mplus(I, m)
for allm
of typeM
Q. What is |+|
?
This is just scalaz shorthand (or ASCII madness, ymmv) for the
mplus
binary operation
Q. What is ~
?
It is a unary operator meaning "or identity" which is retrofitted (using scala's implicit conversions) by the scalaz library onto
Option[M]
ifM
is a monoid. Obviously a non-empty option returns its contents; an empty option is replaced by the monoid's identity.
Q. What is asMA.sum
?
A
Foldable
is basically a datastructure which can be folded over (likefoldLeft
, for example). Recall thatfoldLeft
takes a seed value and an operation to compose successive computations. In the case of summing a monoid, the seed value is the identityI
and the operation ismplus
. You can hence callasMA.sum
on aFoldable[M : Monoid]
. You might need to useasMA
because of the name clash with the standard library'ssum
method.
def addOpts(xs: Option[Int]*) = xs.flatten.sum
This will work for any number of inputs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With