3

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.

Community
  • 1
  • 1
0__
  • 66,707
  • 21
  • 171
  • 266

1 Answers1

1

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

EECOLOR
  • 11,184
  • 3
  • 41
  • 75
  • "`IterableLike` demands that link"—why? and how? Its signature is `trait IterableLike[+A, +Repr]` with no constraints on `Repr`, and in particular not requiring `Repr` to have a type parameter on its own. – 0__ Mar 15 '13 at 14:07
  • You are right, I went back to the documentation and couldn't find it. In the source it is documented: `@tparam Repr the type of the actual collection containing the elements`. All implementations of `IterableLike` use it like this: `Seq[A] extends IterableLike[A, Seq[A]]` (usually via a another trait, `SeqLike` in this case). – EECOLOR Mar 16 '13 at 11:21