5

假设我有一个方法可以将(两个元素上的函数)转换为(两个序列上的函数):

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

换句话说,结果函数接受两个序列xsand ys,并创建一个由(xs(0) f ys(0), xs(1) f ys(1), ...) So 组成的新序列,例如,如果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方法,我还尝试了丰富我的库模式:

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 中的类型推断是从左到右的,因此在考虑零件(_+_)之前需要先弄清楚类型。.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!

reduceLeft期望seqed返回类型Bwhere B >: Int。因此似乎seqed无法知道确切的类型,因此我们必须提供注释。这个问题的更多信息。

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]不是一个有效的替换。

于 2011-12-04T03:36:13.527 回答