I'd like to create a generic type hierarchy for representing graphs. In particular, I'd like like to have classes Graph and Node, and I want that for every Graph type, there is a corresponding Node type and if I create a generic function for manipulating Graphs, I want this function to use the actual Node type. An example that I tried
trait GNode[Graph]
{
... functions to get edges from this vertex, etc. ...
}
trait Graph
{
type Node <: GNode[Graph]
}
def dfs[G <: Graph](g : G, nodeAction : G#Node => Unit) = ... code ...
but this didn't work, because when I did
class ConcreteGraph extends Graph
{
class Node extends GNode[ConcreteGraph] { ... }
}
the dfs function would not accept a function of type ConcreteGraph#Node=>Unit
as nodeAction
, but only AnyRef=>Unit
or GNode[ConcreteGraph]=>Unit
.
To be clearer, If I did it in C++, I'd do something like
template <class T> struct graph_traits;
template <> struct graph_traits<concrete_graph>
{ typedef concrete_graph::node node_type; }
template <class G>
void dfs(const G& g, boost::function<void(
const graph_traits<G>::node_type&)> action) { ... }