Próbuję użyć odpowiedzi a preceding question, aby zaimplementować małą bibliotekę wykresów. Chodzi o to, aby rozważyć wykresy jako kolektory, w których wierzchołki zawijają elementy kolekcji.Parametry typu mieszania i typy abstrakcyjne w scala
Chciałbym użyć typów abstrakcyjnych do reprezentowania typów Vertex i Edge (ze względu na bezpieczeństwo typów) i chcę użyć parametrów typu do przedstawienia typu elementów kolekcji (ponieważ chcę je łatwo zdefiniować podczas tworzenia instancji).
Jednak próbując najbardziej podstawowy przykład, o którym mogę myśleć, utknąłem z błędami kompilacji. Oto przykład:
package graph
abstract class GraphKind[T] {
type V <: Vertex[T]
type G <: Graph[T]
def newGraph(): G
abstract class Graph[T] extends Collection[T]{
self: G =>
def vertices(): List[V]
def add(t: T): Unit
def size(): Int
def elements(): Iterator[T]
}
trait Vertex[T] {
self: V =>
def graph(): G
def value(): T
}
}
A oto podstawowe implementacje:
class SimpleGraphKind[T] extends GraphKind[T] {
type G = GraphImpl[T]
type V = VertexImpl[T]
def newGraph() = new GraphImpl[T]
class GraphImpl[T] extends Graph[T] {
private var vertices_ = List[V]()
def vertices = vertices_
def add(t: T) { vertices_ ::= new VertexImpl[T](t,this) }
def size() = vertices_.size
def elements() = vertices.map(_.value).elements
}
class VertexImpl[T](val value: T, val graph: GraphImpl[T]) extends Vertex[T] {
override lazy val toString = "Vertex(" + value.toString + ")"
}
}
Kiedy próbuje skompilować, otrzymuję:
/prg/ScalaGraph/study/Graph.scala:10: error: illegal inheritance;
self-type GraphKind.this.G does not conform to Collection[T]'s selftype Collection[T]
abstract class Graph[T] extends Collection[T]{
^
/prg/ScalaGraph/study/Graph.scala:33: error: illegal inheritance;
self-type SimpleGraphKind.this.GraphImpl[T] does not conform to SimpleGraphKind.this.Graph[T]'s selftype SimpleGraphKind.this.G
class GraphImpl[T] extends Graph[T] {
^
/prg/ScalaGraph/study/Graph.scala:36: error: type mismatch;
found : SimpleGraphKind.this.VertexImpl[T]
required: SimpleGraphKind.this.V
def add(t: T) { vertices_ ::= new VertexImpl[T](t,this) }
^
/prg/ScalaGraph/study/Graph.scala:38: error: type mismatch;
found : Iterator[T(in class SimpleGraphKind)]
required: Iterator[T(in class GraphImpl)]
def elements() = vertices.map(_.value).elements
^
/prg/ScalaGraph/study/Graph.scala:41: error: illegal inheritance;
self-type SimpleGraphKind.this.VertexImpl[T] does not conform to SimpleGraphKind.this.Vertex[T]'s selftype SimpleGraphKind.this.V
class VertexImpl[T](val value: T, val graph: GraphImpl[T]) extends Vertex[T] {
^
5 errors found
mam absolutnie żadnego pojęcia o znaczeniu te błędy ... Jeśli jednak specjalizuję się w typie T w implementacji (class SimpleGraphKind extends GraphKind[Int]
, otrzymuję tylko pierwszy błąd:
Masz jakieś pomysły?
Czy możesz wyjaśnić, dlaczego chcesz, aby wykres był zbiorem? –
Jedną z aplikacji tej biblioteki byłoby zaimplementowanie rodzaju automatów komórkowych na wykresie (drugim jest złożone badanie sieci). Wtedy może być miło uzyskać dostęp bezpośrednio do obiektów Cell zamkniętych w wierzchołkach ... Ale jeśli masz pomysł na rozwiązanie bez wykresu jako funkcji kolekcji, również mnie to interesuje. – paradigmatic
Nadal nie jestem pewien, czy widzę połączenie. W jaki sposób odróżnisz swoją bibliotekę graficzną od, powiedzmy, JGraphT? Czy jest to funkcjonalne podejście do wykresów? –