首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用enrich-my-library对匿名函数进行类型推断

使用enrich-my-library对匿名函数进行类型推断
EN

Stack Overflow用户
提问于 2011-11-30 23:48:33
回答 3查看 290关注 0票数 5

假设我有一个方法,它把一个(两个元素上的函数)变成一个(两个序列上的函数):

代码语言:javascript
复制
def seqed[T](f: (T,T) => T): (Seq[T], Seq[T]) => Seq[T] = (_,_).zipped map f

换句话说,生成的函数接受两个序列xsys,并创建一个由(xs(0) f ys(0), xs(1) f ys(1), ...)组成的新序列,因此,例如,如果xssSeq(Seq(1,2),Seq(3,4))f(a: Int, b: Int) => a + b,我们可以这样调用它:

代码语言:javascript
复制
xss reduceLeft seqed(f)         // Seq(4, 6)

或者使用匿名函数:

代码语言:javascript
复制
xss reduceLeft seqed[Int](_+_)

这很好;摆脱[Int]类型参数会很好,但我不知道怎么做(有什么想法吗?)

为了让它看起来更像tupled方法,我还尝试了enrich-my-library模式:

代码语言:javascript
复制
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)

对于一个预定义的函数,它工作得很好,但是对于匿名函数来说就不太好用了

代码语言:javascript
复制
xss reduceLeft f.seqed
xss reduceLeft ((_:Int) + (_:Int)).seqed

有没有其他方法可以重新表述,以便推断类型,并使用类似以下的语法:

代码语言:javascript
复制
// pseudocode
xss reduceLeft (_+_).seqed         // ... or failing that
xss reduceLeft (_+_).seqed[Int]

?或者我对类型推断的要求太高了?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-12-04 11:36:14

中需要类型批注的原因

代码语言:javascript
复制
xss reduceLeft seqed[Int](_+_)

但不是在

代码语言:javascript
复制
xs zip ys map Function.tupled(_+_)

这是由于mapreduceLeft的类型要求不同造成的。

代码语言:javascript
复制
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

代码语言:javascript
复制
implicit def withReduceL[T](xs: Seq[T]) = new {
  def reduceL(f: (T, T) => T) = xs reduceLeft f
}

测试:

代码语言:javascript
复制
scala> Seq(Seq(1,2,3), Seq(2,2,2)) reduceL seqed(_+_)
res1: Seq[Int] = List(3, 4, 5)

现在的问题是,无论有没有[Int]参数,这在Seq的子类型(例如List)上都不起作用:

代码语言:javascript
复制
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]不是有效的替换。

票数 0
EN

Stack Overflow用户

发布于 2011-12-01 05:24:20

你不能按你想要的方式去做,但是看看Function.tupled,它是.tupled的对立面,它解决了同样的问题。

代码语言:javascript
复制
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)
票数 5
EN

Stack Overflow用户

发布于 2011-12-01 02:36:45

我很确定你的要求太高了。Scala goes from left to right中的类型推断,所以在考虑.sedeq部分之前,首先需要弄清楚(_+_)的类型。而且那里没有足够的信息。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8328748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档