濃縮マイライブラリーを使用した匿名関数に推論をタイプします
-
26-10-2019 - |
質問
(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), ...)
したがって、たとえば、場合 xss
は Seq(Seq(1,2),Seq(3,4))
と f
は (a: Int, b: Int) => a + b
, 、このように呼び出すことができます:
xss reduceLeft seqed(f) // Seq(4, 6)
または匿名関数を使用してください:
xss reduceLeft seqed[Int](_+_)
これはかなり良いです。を取り除くのはいいことです [Int]
引数を入力しますが、私はどのようにわかりません(アイデアはありますか?)。
もう少しのように感じさせるために tupled
方法、私はまた、濃縮 - マイライブラリーパターンを試しました:
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]
?それとも、私はあまりにも多くのタイプの推論を求めていますか?
解決 3
タイプの注釈が必要な理由
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!
reduceLeft
期待する seqed
タイプを返すには B
どこ B >: Int
. 。したがって、正確なタイプのようです seqed
知らないので、注釈を提供する必要があります。詳細 この質問.
これを克服する1つの方法は、再実装をすることです reduceLeft
下限なし。
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]
有効な代替ではありません。
他のヒント
あなたはあなたが望むようにそれをすることはできませんが、見てください 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)
私はあなたがかなり確信しています それは あまりにも多くを尋ねる。 Scalaの推論を入力します 左から右に行きます, 、したがって、タイプ (_+_)
検討する前に最初に把握する必要があります .sedeq
部。そこには十分な情報がありません。