Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use functional combinators on Scala Tuples?

'map' preserves the number of elements, so using it on a Tuple seems sensible.

My attempts so far:

scala> (3,4).map(_*2)     error: value map is not a member of (Int, Int)        (3,4).map(_*2)              ^ scala> (3,4).productIterator.map(_*2) error: value * is not a member of Any        (3,4).productIterator.map(_*2)                                   ^ scala> (3,4).productIterator.map(_.asInstanceOf[Int]*2) res4: Iterator[Int] = non-empty iterator  scala> (3,4).productIterator.map(_.asInstanceOf[Int]*2).toList res5: List[Int] = List(6, 8) 

It looks quite painful... And I haven't even begun to try to convert it back to a tuple.
Am I doing it wrong? Could the library be improved?

like image 960
Eldritch Conundrum Avatar asked Feb 26 '10 06:02

Eldritch Conundrum


1 Answers

In general, the element types of a tuple aren't the same, so map doesn't make sense. You can define a function to handle the special case, though:

scala> def map[A, B](as: (A, A))(f: A => B) =       as match { case (a1, a2) => (f(a1), f(a2)) }  map: [A,B](as: (A, A))(f: (A) => B)(B, B)  scala> val p = (1, 2)     p: (Int, Int) = (1,2)  scala> map(p){ _ * 2 } res1: (Int, Int) = (2,4) 

You could use the Pimp My Library pattern to call this as p.map(_ * 2).

UPDATE

Even when the types of the elements are not the same, Tuple2[A, B] is a Bifunctor, which can be mapped with the bimap operation.

scala> import scalaz._ import scalaz._  scala> import Scalaz._ import Scalaz._  scala> val f = (_: Int) * 2 f: (Int) => Int = <function1>  scala> val g = (_: String) * 2 g: (String) => String = <function1>  scala> f <-: (1, "1") :-> g res12: (Int, String) = (2,11) 

UPDATE 2

http://gist.github.com/454818

like image 55
retronym Avatar answered Sep 27 '22 20:09

retronym