Use functional combinators on Scala Tuples?

'map' saves the number of elements, so using it on Tuple seems reasonable.

My attempts:

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 pretty painful ... And I didn't even start trying to convert it into a tuple.
Am I doing it wrong? Can the library be improved?

+43
dictionary scala tuples shapeless
Feb 26 '10 at 6:27
source share
3 answers

shapeless Supports displaying and collapsing tuples through an intermediate HList ,

Sample REPL Session,

 scala> import shapeless._ ; import Tuples._ import shapeless._ import Tuples._ scala> object double extends (Int -> Int) (_*2) defined module double scala> (3, 4).hlisted.map(double).tupled res0: (Int, Int) = (6,8) 

If the elements of a tuple are of different types, you can map the polymorphic function to specific types of cases,

 scala> object frob extends Poly1 { | implicit def caseInt = at[Int](_*2) | implicit def caseString = at[String]("!"+_+"!") | implicit def caseBoolean = at[Boolean](!_) | } defined module frob scala> (23, "foo", false, "bar", 13).hlisted.map(frob).tupled res1: (Int, String, Boolean, String, Int) = (46,!foo!,true,!bar!,26) 

Update

In the form of shapeless 2.0.0-M1 , binding to tuples directly is supported. The above examples now look like this:

 scala> import shapeless._, poly._, syntax.std.tuple._ import shapeless._ import poly._ import syntax.std.tuple._ scala> object double extends (Int -> Int) (_*2) defined module double scala> (3, 4) map double res0: (Int, Int) = (6,8) scala> object frob extends Poly1 { | implicit def caseInt = at[Int](_*2) | implicit def caseString = at[String]("!"+_+"!") | implicit def caseBoolean = at[Boolean](!_) | } defined module frob scala> (23, "foo", false, "bar", 13) map frob res1: (Int, String, Boolean, String, Int) = (46,!foo!,true,!bar!,26) 
+28
May 7 '12 at
source share

In general, the types of tuple elements do not match, so the map does not make sense. You can define a function to handle a special case:

 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 can use the Pimp My Library template to call it p.map(_ * 2) .

UPDATE

Even if the element types do not match, Tuple2[A, B] is a Bifunctor that can be matched to a bimap .

 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

+35
Feb 26 '10 at 7:11
source share

The map function gets A => B and returns F[B] .

 def map[A, B](f: A => B) : F[B] 

As the retronym wrote, Tuple2 [A, B] is a Bifunctor, so you can look for a bimap function in a scalp or cat.
bimap is a function that displays both sides of a tuple:

 def bimap[A, B, C, D](fa: A => C, fb: B => D): Tuple2[C, D] 

Since Tuple [A, B] contains 2 values, and only one value can be displayed (according to the convention, the correct value), you can simply return the same value to the left side and use the right function to display the correct tuple value.

 (3, 4).bimap(identity, _ * 2) 
+1
Dec 14 '18 at 19:23
source share



All Articles