Type inference for anonymous functions using the enrichment library

Let's say I have a method that turns (a function on two elements) into (a function on two sequences):

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

In words, the resulting function takes two sequences xsand yscreates a new sequence consisting of (xs(0) f ys(0), xs(1) f ys(1), ...) So, for example, if xss- Seq(Seq(1,2),Seq(3,4))and f- (a: Int, b: Int) => a + b, we can call it this way:

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

or with an anonymous function:

xss reduceLeft seqed[Int](_+_)

This is pretty good; it would be nice to get rid of the type argument [Int], but I don't see how (any ideas?).

To make it tupledlook a bit like a method , I also tried the my-library enrichment pattern:

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)

For a predefined function, this works fine, but ugly with anonymous

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

, , , :

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

? ?

+5
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 , . .

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] .

0

, , 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)
+5

I'm sure you ask too much. Type inference in Scala goes from left to right , so the type (_+_)must be evaluated first before considering the .sedeqpart. And there is not enough information there.

+4
source

All Articles