Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a pairwise difference to generic collections - implicit resolution doesn't kick in

Ok, so I have this:

implicit final class RichIterableLike[A, Repr <: IterableLike[A, Repr]](val it: Repr) 
  extends AnyVal {
  def pairDiff[To](implicit num: Numeric[A], cbf: CanBuildFrom[Repr, A, To]): To = {
    val b     = cbf(it)
    val iter  = it.iterator
    if (iter.hasNext) {
      var pred = iter.next()
      while (iter.hasNext) {
        import num.mkNumericOps
        val succ = iter.next()
        b += succ - pred
        pred = succ
      }
    }
    b.result()
  }
}

This compiles, but doesn't kick in:

val stabs = IndexedSeq(1.0, 2.0, 3.0)
stabs.pairDiff

Gives: value pairDiff is not a member of IndexedSeq[Double]

Explicit conversion works:

new RichIterableLike[Double, IndexedSeq[Double]](stabs).pairDiff

... how to fix this?


EDIT

If I apply the approach of this answer, it works:

implicit final class RichIterableLike[A, CC[~] <: Iterable[~]](val it: CC[A]) 
  extends AnyVal {
  def pairDiff[To](implicit num: Numeric[A], cbf: CanBuildFrom[CC[A], A, To]): To = {
  ...
}

But the question remains, what is the crucial difference that makes the implicit lookup kick in in the latter case.

like image 698
0__ Avatar asked Mar 01 '26 09:03

0__


1 Answers

In order for the implicit lookup to work it needs a link between A and Repr (IterableLike demands that link). You pass it in as an argument, so that argument should be typed as Repr[A]. That means you need to modify your signature so it will look something like this:

RichIterableLike[A, Repr[X] <: IterableLike[X, Repr[X]]](val it: Repr[A])

With the above signature you say:

I have an object that accepts a type parameter, I will name that object Repr and when you pass it in I would like to capture the type parameter as well. I will name that type parameter A. As an extra condition I want the type of Repr to conform to the signature of IterableLike

like image 166
EECOLOR Avatar answered Mar 03 '26 21:03

EECOLOR