As we know, matching can’t see type parameters because of erasure:
Welcome to Scala 2.12.3 (OpenJDK 64-Bit Server VM, Java 1.8.0_141).
Type in expressions for evaluation. Or try :help.
scala> def m(a: AnyRef):String = a match { case strings: Iterable[String] => strings.mkString(" "); case _ => "Yo!" }
<console>:11: warning: non-variable type argument String in type pattern Iterable[String] (the underlying of Iterable[String]) is unchecked since it is eliminated by erasure
def m(a: AnyRef):String = a match { case strings: Iterable[String] => strings.mkString(" "); case _ => "Yo!" }
^
m: (a: AnyRef)String
But what does one do if we want to match only Iterable[T] for specific T? Add a guard that checks the type of every element? Create an extractor that takes TypeTags?
You need to back up and ask yourself how you got into this situation. What is the actual problem you are trying to solve? Whether TypeTag provides a way out depends on that.
The trouble is that whether a value of type Iterable[T] for some T is of type Iterable[String] is quite a different question from that of whether every element is a String. For example, given Q, a strict subtype of String, if xs: Iterable[Q], then xs: Iterable[String], and every element is a String, but Q != String. You can go the other way, too: Iterable[Any]("hi").
Suppose that you took every element being String as implying that the Iterable itself is Iterable[String].
package mtwp
// The only purpose of this trait is to demonstrate the sound covariant GADT
// consequence of a successful match; that is, "what is the meaning of
// determining that an `Iterable` is an `Iterable[String]`?"
trait StringIterable extends Iterable[String]
object Funs {
def isStrings[A](xs: Iterable[A]): Option[String <:< A] = xs match {
// Once again, I emphasize that the only purpose of `StringIterable` is to
// prove that the return type of `isStrings` makes sense. And this case is
// sound.
case _: StringIterable =>
Some(implicitly[String <:< A])
// But this case is not, as we'll see shortly.
case _ if xs forall (_.isInstanceOf[String]) =>
Some(implicitly[String <:< String].asInstanceOf[String <:< A])
case _ => None
}
val foo = "foo"
val bar = "bar"
// I could just pass an empty iterable, and it wouldn't be cheating. But just
// for skepticism's sake, I won't pass an empty iterable.
val explosion: Option[String <:< foo.type] =
isStrings[foo.type](Seq(foo))
val totallyAFoo: Option[foo.type] = explosion map (_(bar))
// Of course an empty iterable lets you just prove utter foolishness.
val unsafeStroerce: String <:< Nothing =
isStrings[Nothing](Iterable.empty).get
val magic: Option[ClassLoader] = Some(unsafeStroerce("hi!"))
}
////////
Welcome to Scala 2.12.3 (OpenJDK 64-Bit Server VM, Java 1.8.0_112).
Type in expressions for evaluation. Or try :help.
scala> mtwp.Funs.totallyAFoo
res0: Option[mtwp.Funs.foo.type] = Some(bar)
scala> mtwp.Funs.magic
res1: Option[ClassLoader] = Some(hi!)
By the way, the unsoundness of conflating the two concepts has nothing to do with erasure; it would still be unsound had we followed the siren song and foundered upon the craggy bluffs of “reified generics”. So, as @SethTisue mentioned, regardless, it depends on what you want to do.
My specs are as follows: accept an object of any type. If it is of a
particular type Store, or Iterable[Store], take some special action. For
any other type of object, take some default action.
I’m happy to accept as “Iterable[Store]” an Iterable whose elements are
all of type Store. I haven’t made up my mind regarding empty Iterables, but
maybe for now I can accept them as Iterable[Store].
I’m assuming I can do this by writing a generic “Iterable[T]” extractor
using type tags. I could also write an extractor hard-coded for the type
Store.
I was assuming this is a common case and there might be some library
support, but maybe that’s not the case.
One question to answer to refine your approach is: why do you have to take an AnyRef here? Depending on your answer, it may not even be meaningful to take Iterable[Store] in any other form than “iterable whose elements are all Stores”.