'map'は要素の数を保持するため、タプルで使用するのが賢明なようです。
これまでの私の試み:
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)
それはかなり苦痛に見えます...そして私はそれをタプルに戻すことさえ試み始めていません。
私はそれを間違っていますか?ライブラリを改善できますか?
shapeless 中間の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)
タプルの要素が異なるタイプである場合、タイプ固有のケースでポリモーフィック関数を使用してマップできます。
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)
一般に、タプルの要素タイプは同じではないため、マップは意味がありません。ただし、特別な場合を処理する関数を定義できます。
_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)
として呼び出すことができます。
[〜#〜]更新[〜#〜]
要素のタイプが同じでない場合でも、_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)
_
UPDATE 2
map関数はA => B
を取得し、F[B]
を返します。
def map[A, B](f: A => B) : F[B]
レトロニムが書いたように、Tuple2 [A、B]はBifunctorであるため、scalazまたはcatsでbimap関数を探すことができます。
bimapは、タプルの両側をマップする関数です。
def bimap[A, B, C, D](fa: A => C, fb: B => D): Tuple2[C, D]
タプル[A、B]は2つの値を保持し、1つの値のみをマップできるため(慣例により右側の値)、左側に同じ値を返し、右側の関数を使用してタプルの右側の値にマップできます。 。
(3, 4).bimap(identity, _ * 2)