14

Is there a easy way to add tuples which contain addable elements like Int, Doubles etc? For examples,

(1,2) + (1,3) = (2,5)
Valy Dia
  • 2,781
  • 2
  • 12
  • 32
Arun
  • 645
  • 7
  • 16
  • what are you trying to achieve? mostly using tuples for such thing (might be) considered bad style. – Stefan Kunze Oct 26 '13 at 14:03
  • tuples aren't intended for this type of thing. They're just a convenient wrapper for methods that return multiple values, which is why they don't have a host of useful functions like collections do. – Luigi Plinge Oct 26 '13 at 14:31
  • 1
    I was trying to reduce a list of tuples. I am using tuples to do some map reduce type operations. Customs classes and objects seems overkill. – Arun Oct 26 '13 at 15:24
  • @Arun, if you are working with lists of tuples you might find (my) project https://github.com/marklister/product-collections useful. – Mark Lister Oct 27 '13 at 09:11

3 Answers3

20

Scalaz

import scalaz._, Scalaz._

scala> (1, 2.5) |+| (3, 4.4)
res0: (Int, Double) = (4,6.9)

There is an operator |+| for any class A with implicit Semigroup[A] in scope. For Int |+| is + by default (you could redefine it in your code).

There is an implicit Semigroup[(A, B)] for all tuples if there is implicit Semigroup for A and B.

See Scalaz cheat sheet.

senia
  • 37,745
  • 4
  • 88
  • 129
13

+1 for the the Scalaz answer :-)

If you want a very simple version of it you could define an implicit class like:

implicit class TuppleAdd(t: (Int, Int)) {
  def +(p: (Int, Int)) = (p._1 + t._1, p._2 + t._2)
}

(1, 1) + (2, 2) == (3, 3)

// update1, more generic version for numbers:

So this is the simplest version, defined only for Ints, we could generify it for all numeric values using Scala's Numeric:

implicit class Tupple2Add[A : Numeric, B : Numeric](t: (A, B)) {
  import Numeric.Implicits._

  def + (p: (A, B)) = (p._1 + t._1, p._2 + t._2)
}

(2.0, 1) + (1.0, 2) == (3.0, 3)
Konrad 'ktoso' Malawski
  • 13,102
  • 3
  • 47
  • 52
  • 2
    There is not only `Int` in the question. You could improve your answer with `math.Numeric` like this: `implicit class TuppleAdd[A : Numeric, B : Numeric](t: (A, B)) { import Numeric.Implicits._; def +(p: (A, B)) = (p._1 + t._1, p._2 + t._2) }`. – senia Oct 26 '13 at 13:00
  • That is true :-) I also thought about a version with a structural type, but let's not go there maybe ;-) – Konrad 'ktoso' Malawski Oct 26 '13 at 13:06
  • 2
    I've also tried to implement `implicit def tupleIsNumeric[A : Numeric, B : Numeric]: Numeric[(A, B)]`, but there is [an issue](http://pastebin.com/fyty7mMy) with `+` operator (`-` and `*` works fine). – senia Oct 26 '13 at 13:24
  • 1
    Does your `+` issue perchance have to do with this?: http://stackoverflow.com/questions/6906742/scala-implicit-conversion-scope-issues – metasim Feb 20 '14 at 01:55
1

This works with Cats as well, and similar to the scalaz answer:

> (1,2) |+| (1,3)
res3: (Int, Int) = (2, 5)

And likewise, it relies on Semigroup.

Valy Dia
  • 2,781
  • 2
  • 12
  • 32