假设我有一个方法可以将(两个元素上的函数)转换为(两个序列上的函数):
def seqed[T](f: (T,T) => T): (Seq[T], Seq[T]) => Seq[T] = (_,_).zipped map f
在单词中,结果函数采用两个序列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
方法,我还尝试了rich-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]
?或者我是否过多地询问类型推断?
答案 0 :(得分: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)
的反对部分,可以解决同样的问题。
{{1}}
答案 1 :(得分:4)
我很确定你 要求太多了。在Scala goes from left to right中输入推理,因此在考虑(_+_)
部分之前,需要首先计算出.sedeq
的类型。那里没有足够的信息。
答案 2 :(得分: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
返回B
类型B >: Int
。因此似乎无法知道seqed
的精确类型,因此我们必须提供注释。有关this question的更多信息。
克服这种情况的一种方法是在没有下限的情况下重新实现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]
不是有效替代。