Background info: I'm currently trying to set up a generic graph library that includes a few different search algorithms (I've started with Dijkstra's). I've set up a few traits to represent methods that would be found in certain types of graphs (e.g. weighted, directed):
trait GraphOps[V,E] { ... }
trait WeightedGraphOps[V,E] extends GraphOps[V,E] { ... }
trait DirectedGraphOps[V,E] extends GraphOps[V,E] { ... }
object GraphOps{
def Dijkstra[V,E,G <: WeightedGraphOps[V,E] with DirectedGraphOps[V,E]](graph:G, start:V) = { ... }
}
Elsewhere, I have a class as the concrete implementation of the weighted, directed graph that I want to run Dijkstra's algorithm on:
class GraphMap[T](...)
extends scala.collection.mutable.Map[Position,T]
with WeightedGraphOps[Position,Edge] with DirectedGraphOps[Position,Edge] { ... }
But when I try to test it out:
val graph = new GraphMap[Int](...)
val (dist, prev) = GraphOps.Dijkstra(graph, Position(0,0))
Question: I get the following error during compilation: error: inferred type arguments [com.dylan.data.Position,Nothing,com.dylan.data.GraphMap[Int]] do not conform to method Dijkstra's type parameter bounds [V,E,G <: com.dylan.data.WeightedGraphOps[V,E] with com.dylan.data.DirectedGraphOps[V,E]]
It took me long enough to notice that it's inferring my Edge (E
) type as Nothing
, but I don't see why it's failing to successfully infer that it's supposed to be Edge
. Why is it failing to infer that type parameter, and how can I fix it?
P.S. I tried doing the following, and got it to work, but this seems horribly inconvenient for what was supposed to be a convenience method:
type Helpful = WeightedGraphOps[Position,Edge] with DirectedGraphOps[Position,Edge]
val (dist, prev) = GraphOps.Dijkstra[Position,Edge,Helpful](graph, Position(0,0))