5

(2 つの要素に対する関数) を (2 つのシーケンスに対する関数) に変換するメソッドがあるとします。

def seqed[T](f: (T,T) => T): (Seq[T], Seq[T]) => Seq[T] = (_,_).zipped map f

つまり、結果の関数は 2 つのシーケンスxsとを取りys、 で構成される新しいシーケンスを作成します。(xs(0) f ys(0), xs(1) f ys(1), ...) たとえば、xssisSeq(Seq(1,2),Seq(3,4))fis(a: Int, b: Int) => a + bの場合、次のように呼び出すことができます。

xss reduceLeft seqed(f)         // Seq(4, 6)

または無名関数で:

xss reduceLeft seqed[Int](_+_)

これはかなり良いです。型引数を取り除くのはいいことですが、[Int]方法がわかりません (アイデアはありますか?)。

メソッドのように感じさせるためにtupled、enrich-my-library パターンも試しました。

class SeqFunction[T](f: (T,T) => T) {
  def seqed: (Seq[T], Seq[T]) => Seq[T] = (_,_).zipped map f
}
implicit def seqFunction[T](f: (T,T) => T) = new SeqFunction(f)

事前定義された関数の場合、これはうまく機能しますが、匿名の関数では醜いです

xss reduceLeft f.seqed
xss reduceLeft ((_:Int) + (_:Int)).seqed

型が推論されるようにこれを再定式化できる別の方法はありますか?次のような構文を使用できます。

// pseudocode
xss reduceLeft (_+_).seqed         // ... or failing that
xss reduceLeft (_+_).seqed[Int]

? それとも、型推論を求めすぎているのでしょうか?

4

3 に答える 3

5

あなたはそれをあなたが望むように行うことはできませんが、これとまったく同じ問題を解決するFunction.tupledためのカウンターパートであるを見てください。.tupled

scala> List(1, 2, 3) zip List(1, 2, 3) map (_ + _).tupled
<console>:8: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2))
              List(1, 2, 3) zip List(1, 2, 3) map (_ + _).tupled
                                                   ^
<console>:8: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2))
              List(1, 2, 3) zip List(1, 2, 3) map (_ + _).tupled
                                                       ^

scala> List(1, 2, 3) zip List(1, 2, 3) map Function.tupled(_ + _)
res7: List[Int] = List(2, 4, 6)
于 2011-11-30T21:24:20.020 に答える
4

私はあなたがあまりにも多くを求めていると確信しています。Scala での型推論はleft から rightに進むため、その部分を考慮する前に、 の型を(_+_)最初に把握する必要があります.sedeq。そして、そこには十分な情報がありません。

于 2011-11-30T18:36:44.793 に答える
0

型注釈が必要な理由

xss reduceLeft seqed[Int](_+_)

しかし、そうではありません

xs zip ys map Function.tupled(_+_)

mapは、との間の型要件の違いによるものreduceLeftです。

def reduceLeft [B >: A] (f: (B, A) ⇒ B): B 
def map        [B]      (f: (A) ⇒ B): Seq[B]   // simple version!

reduceLeftseqedtype Bwhereを返すことを期待していB >: Intます。したがって、 の正確な型seqedがわからないようです。そのため、注釈を付ける必要があります。詳細については、この質問を参照してください。

reduceLeftこれを克服する 1 つの方法は、下限なしで再実装することです。

implicit def withReduceL[T](xs: Seq[T]) = new {
  def reduceL(f: (T, T) => T) = xs reduceLeft f
}

テスト:

scala> Seq(Seq(1,2,3), Seq(2,2,2)) reduceL seqed(_+_)
res1: Seq[Int] = List(3, 4, 5)

現在の問題は、パラメーターの有無にかかわらず、これがSeq(例: List)のサブタイプで機能しないことです。[Int]

scala> Seq(List(1,2,3), List(2,2,2)) reduceL seqed(_+_)
<console>:11: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2))
              Seq(List(1,2,3), List(2,2,2)) reduceL seqed(_+_)
                                                          ^

reduceLタイプ の関数が必要です(List[Int], List[Int]) => List[Int]Function2は として定義されているため、有効な置換Function2 [-T1, -T2, +R]ではありません。(Seq[Int], Seq[Int]) => Seq[Int]

于 2011-12-04T03:36:13.527 に答える