Suppose I want every instance of an Item to be a SourceOf that Item, and every SourceOf a subtype of Item to be a SourceOf all instances of that subtype. This seems like a natural way to do it:
object Demo {
trait Item extends SourceOf[this.type]
trait SourceOf[+A <: Item]
}
Obviously this won't work, since this refers to the Demo object, not to each Item instance. (I've tested it.)
How can I tell the Scala compiler that every Item is a source of itself? It should be possible to get the compiler to deduce stuff like:
"Every source of (all) farming implements is a source of the specific farming implement you're looking for."
"If you're looking for the source of a farming implement, and you already have the farming implement, then you need look no further."
Here's an example (written to ignore type erasure for brevity):
trait FarmingImplement extends Item
object TheRototiller extends FarmingImplement
def findSource(item: Item, seq: Seq[SourceOf[_]]): Option[SourceOf[item.type]] =
seq.collectFirst {
case src: SourceOf[item.type] => src
}
val sources = Seq( // example: possible sources of TheRototiller
new SourceOf[Nothing] { override def toString = "Wrong source" },
new SourceOf[FarmingImplement] { override def toString = "Right" },
TheRototiller /* also right */ )
val got = findSource(TheRototiller, sources).get
println(got) // Should print "Right", since the second source in `sources`
// is the first match.
I want the type of got be SourceOf[TheRototiller.type], not SourceOf[Item]. But mainly I want Scala's type system to do the work of determining whether a SourceOf matches a given Item or category of Items.
At least, this gonna solve your problem with passing
this:Example (you'll have to compare
Ts instead ofSourceOfs here):If you need to check types in runtime (as you've shown in example with pattern matching) - I would recomend to use
TypeTag:Usage:
Finally, implementation of
findSource:Examples:
asInstanceOfis used (it's safe to do here) becauseSeqlooses path-dependent type in compile-time and we used runtime-check to match types, so no way to find it for compiler. However, Shapeless2'sHList+Selectorbased implementation might be more pure.