4

Referring to a previous answer of mine on stackoverflow

The core of the complexity is illustrated in just one method:

implicit def traversableToFilterOps[CC[X] <: Traversable[X], T]
(xs: CC[T])(implicit witness: CC[T] <:< TraversableLike[T,CC[T]]) =
  new MoreFilterOperations[CC[T], T](xs)

With two questions:

  1. Is there any way to give the compiler a hint that Map meets the signature CC[X] <: Traversable[X]? I would expect it to match as a Traversable[Tuple2[_,_]] but this doesn't happen. In the end, I had to write a second method taking CC[KX,VX] <: Map[KX,VX], but that feels redundant

  2. witness: CC[T] <:< TraversableLike[T,CC[T]] also seems redundant given the first type parameter, my gut feeling is that this is enforced by the type of Traversable and must always hold true for any possible subclass or value of X, so there should be no reason to explicitly require it as a witness.

If I test this using an existential type in the REPL, then the compiler seems to agree with me:

scala> implicitly[Traversable[X] <:< TraversableLike[X,Traversable[X]] forSome { type X }]
res8: <:<[Traversable[X],scala.collection.TraversableLike[X,Traversable[X]]] forSome { type X } = <function1>

Is there therefore any way to do away with the boilerplate?

Community
  • 1
  • 1
Kevin Wright
  • 49,540
  • 9
  • 105
  • 155

1 Answers1

1

I'm a Scala noob, so please don't shoot me down if this doesn't help.

Assuming this:

class MoreFilterOperations[Repr <% TraversableLike[T,Repr], T] (xs: Repr) {}

Would something like this work?

// t2fo is short for traversableToFilterOps
implicit def t2fo[Repr <% TraversableLike[T, Repr], T](xs: Repr) = 
  new MoreFilterOperations[Repr, T](xs)

// m2fo is short for mapToFilterOps
implicit def m2fo[Repr <% Map[K, V] <% TraversableLike[(K,V), Repr], K, V]
  (xs: Repr) = new MoreFilterOperations[Repr, (K, V)](xs)

This should work because (according to the book I have.. Programming Scala, p264) the following method definition with a view bound:

def m [A <% B](arglist): R = ...

It is effectively the same as this method definition:

def m [A](arglist)(implicit viewAB: A => B): R = ...
mepcotterell
  • 2,670
  • 2
  • 21
  • 28
  • So don't even bother checking for `<: Traversable` in the implicit methods, and cut straight to `<% TraversableLike`. I like it... simple, and certainly sounds plausible for this particular use case. It doesn't help answer the broader question of subclassing in implicits, but still a great idea. now to fire up the REPL and confirm :) – Kevin Wright Feb 20 '11 at 15:21
  • Perhaps the bounds `X <: A <% B` would answer your question about subtyping? Since it should accept any `X` that is a subtype of `A` that has a view in scope that transforms it to a `B`. – mepcotterell Feb 22 '11 at 00:57
  • It's not a complete answer, but you get the green tick anyway for being constructive and adding something of value. – Kevin Wright Mar 05 '11 at 21:09