10

タイプRを返す単一の関数を使用してScalaタプル(またはトリプル、...)の要素をマップしたいと思います。結果は、タイプRの要素を持つタプル(またはトリプル、...)になります。

OK、タプルの要素が同じタイプのものである場合、マッピングは問題ではありません。

scala> implicit def t2mapper[A](t: (A,A)) = new { def map[R](f: A => R) = (f(t._1),f(t._2)) }
t2mapper: [A](t: (A, A))java.lang.Object{def map[R](f: (A) => R): (R, R)}

scala> (1,2) map (_ + 1)
res0: (Int, Int) = (2,3)

しかし、このソリューションを一般的にすること、つまり、同じ方法で異なるタイプの要素を含むタプルをマップすることも可能ですか?

例:

class Super(i: Int)
object Sub1 extends Super(1)
object Sub2 extends Super(2)

(Sub1, Sub2) map (_.i)

戻る必要があります

(1,2): (Int, Int)

しかし、マッピング関数がSub1とSub2のスーパータイプを決定するように解決策を見つけることができませんでした。タイプ境界を使用しようとしましたが、私のアイデアは失敗しました。

scala> implicit def t2mapper[A,B](t: (A,B)) = new { def map[X >: A, X >: B, R](f: X => R) = (f(t._1),f(t._2)) }
<console>:8: error: X is already defined as type X
       implicit def t2mapper[A,B](t: (A,B)) = new { def map[X >: A, X >: B, R](f: X => R) = (f(t._1),f(t._2)) }
                                                                    ^
<console>:8: error: type mismatch;
 found   : A
 required: X
 Note: implicit method t2mapper is not applicable here because it comes after the application point and it lacks an explicit result type
       implicit def t2mapper[A,B](t: (A,B)) = new { def map[X >: A, X >: B, R](f: X => R) = (f(t._1),f(t._2)) }

ここでX >: BオーバーライドするようX >: Aです。Scalaは複数のタイプに関するタイプ境界をサポートしていませんか?はいの場合、なぜですか?

4

5 に答える 5

12

私はこれがあなたが探しているものだと思います:

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)

これを行うためのより「機能的な」方法は、2つの別々の機能を使用することです。

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)
于 2010-10-26T09:51:23.880 に答える
4

私はscalaタイプの天才ではありませんが、おそらくこれは機能します:

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)) }
于 2010-10-26T09:55:00.390 に答える
0

ここでのより深い質問は、「なぜこれにタプルを使用しているのですか?」です。

タプルは設計上異質であり、非常に異なるタイプの品揃えを含めることができます。関連するもののコレクションが必要な場合は、...ドラムロール...コレクションを使用する必要があります!

またははパフォーマンスに影響を与えず、このSetSequenceの作業にはるかに適しています。結局のところ、それは彼らが設計されているものです。

于 2010-10-26T10:15:55.123 に答える
0

適用する2つの機能が同じでない場合

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

私がこの回答を提供した主な理由は、タプルのリストに対して機能することです(SomeをListに変更し、getを削除するだけです)。

于 2013-11-30T13:17:44.383 に答える
0

これは、シェイプレスを使用して簡単に実現できますが、マップを実行する前に、まずマッピング関数を定義する必要があります。

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)

(このように、の定義のval前にを追加する必要がありました。これにより、外部からアクセスできるようになります)iSuperclass Super(val i: Int)

于 2014-07-20T16:54:59.560 に答える