在Scala元组上使用函数组合器?

“地图”保留了元素的数量,所以在Tuple上使用它似乎是明智的。

我到目前为止的尝试:

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) 

它看起来很痛苦…我甚至还没有开始尝试将它转换回元组。
我做错了吗? 图书馆可以改进吗?

无形状支持通过中间HList表示映射和折叠元组,

示例REPL会话,

 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) 

如果元组的元素是不同types的,那么可以使用具有特定types的情况来映射多态函数,

 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) 

更新

从元组的无形2.0.0-M1映射直接支持。 上面的例子现在看起来像这样,

 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) 

一般来说,一个元组的元素types是不一样的,所以地图是没有意义的。 你可以定义一个函数来处理这个特例,但是:

 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) 

您可以使用Pimp My Library模式将其称为p.map(_ * 2)

UPDATE

即使元素的types不相同, Tuple2[A, B]也是一个Bifunctor ,它可以用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) 

更新2

http://gist.github.com/454818