General 'map' function for Scala tuples?

橙三吉。 提交于 2019-12-04 02:44:03

I think this is what you're looking for:

implicit def t2mapper[X, A <: X, B <: X](t: (A,B)) = new {
  def map[R](f: X => R) = (f(t._1), f(t._2))
}

scala> (Sub1, Sub2) map (_.i)                             
res6: (Int, Int) = (1,2)

A more "functional" way to do this would be with 2 separate functions:

implicit def t2mapper[A, B](t: (A, B)) = new { 
  def map[R](f: A => R, g: B => R) = (f(t._1), g(t._2)) 
}       

scala> (1, "hello") map (_ + 1, _.length)                                         
res1: (Int, Int) = (2,5)

I’m not a scala type genius but maybe this works:

implicit def t2mapper[X, A<:X, B<:X](t: (A,B)) = new { def map[A, B, R](f: X => R) = (f(t._1),f(t._2)) }

The deeper question here is "why are you using a Tuple for this?"

Tuples are hetrogenous by design, and can contain an assortment of very different types. If you want a collection of related things, then you should be using ...drum roll... a collection!

A Set or Sequence will have no impact on performance, and would be a much better fit for this kind of work. After all, that's what they're designed for.

For the case when the two functions to be applied are not the same

scala> Some((1, "hello")).map((((_: Int) + 1 -> (_: String).length)).tupled).get
res112: (Int, Int) = (2,5)

The main reason I have supplied this answer is it works for lists of tuples (just change Some to List and remove the get).

This can easily be achieved using shapeless, although you'll have to define the mapping function first before doing the map:

object fun extends Poly1 {
  implicit def value[S <: Super] = at[S](_.i) 
}

(Sub1, Sub2) map fun // typed as (Int, Int), and indeed equal to (1, 2)

(I had to add a val in front of i in the definition of Super, this way: class Super(val i: Int), so that it can be accessed outside)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!