2011-07-30 18 views
5

背景情報:私は現在、いくつかの異なる検索アルゴリズム(私はDijkstraで始まっています)を含む一般的なグラフライブラリを設定しようとしています。私は(例えば、加重監督)グラフの特定の種類で見られる方法を表すために、いくつかの特性を設定している:他の場所Scalaが正しい型引数を推論しません

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) = { ... } 
} 

、私は重み付き有向グラフの具体的な実装としてクラスを持っています

class GraphMap[T](...) 
extends scala.collection.mutable.Map[Position,T] 
with WeightedGraphOps[Position,Edge] with DirectedGraphOps[Position,Edge] { ... } 

しかし、私はそれをテストしようとすると:私は上のダイクストラのアルゴリズムを実行すること

val graph = new GraphMap[Int](...) 
val (dist, prev) = GraphOps.Dijkstra(graph, Position(0,0)) 

が質問: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]]
私のEdge(E)タイプをNothingと推測しているのに気付くほど時間がかかりましたが、なぜそれがEdgeであると推測できないのかわかりません。その型パラメータを推測できないのはなぜですか、どうすれば修正できますか?

P.S.私は、次のことをやってみました、それが動作するようになったが、これは便利な方法になるはずだった何のために恐ろしく不便なようだ:

type Helpful = WeightedGraphOps[Position,Edge] with DirectedGraphOps[Position,Edge] 
val (dist, prev) = GraphOps.Dijkstra[Position,Edge,Helpful](graph, Position(0,0)) 
+0

既にグラフライブラリがありますか? –

+0

私は趣味のためにこれをやっているので、周りを検索して数分で決定的な答えにつながっていないので、私は自分自身を一緒に置くかもしれないと思った。 – Dylan

+0

私は何の言葉を正確にGoogleにしたのですか?私は 'スカラーグラフライブラリ'を試して、これを持っています:http://code.google.com/p/scala-graphs/あなたのためにこれはありませんか? – AndreasScheinert

答えて

6

Danielはおそらく、既存のScala型推論エンジンがより直接的な情報を必要としていることは間違いありません。EEdgeである必要があります。また、将来の改善のために型推論が意図的に不十分であると私は理解しています。

とにかく、タイプ推論の問題を解決する別のアプローチをとることができます。タイプのメンバーではなく、パラメータを使用します。以下の自己完結型コードで私が意味することを説明しました。重要な考え方は、タイプEとタイプVGraphOpsタイプの一部になりますが、Dijkstraメソッドのようにタイプの詳細化を使用することによって、引き続きタイプパラメータとして浮上することができます。

trait GraphOps { type E; type V } 
trait WeightedGraphOps extends GraphOps { } 
trait DirectedGraphOps extends GraphOps { } 
object GraphOps{ 
    def Dijkstra[V0, G <: (WeightedGraphOps{type V = V0}) 
         with (DirectedGraphOps{type V = V0})] 
     (graph:G, start:V0) = { } 
} 

case class Position(x: Int, y: Int) 
case class Edge() 

case class GraphMap[T]() extends WeightedGraphOps with DirectedGraphOps { 
    type E = Edge 
    type V = Position 
} 

object Test { 
    val graph = new GraphMap[Int]() 
    GraphOps.Dijkstra(graph, Position(0,0)) 
} 

編集この型部材アプローチの一つの潜在的制限は、それがメソッドDijkstraタイプパラメータGに以下の制約を置くあります。具体的には、境界WeightedGraphOpsDirectedGraphOpsは同じタイプのメンバーEを持つように制約されません。私は最初に報告した型推論の問題にぶつかることなくこれを解決する方法がわかりません。 1つのアプローチは、この質問のパターンです:Why do these type arguments not conform to a type refinement?しかし、Scalaコンパイラはそれを処理できないようです。

編集2上記の段落は無視してください。コメントにDylanが言及したように、このdiamond inheritance状況では、Scalaは型Eの整合性をうまく保証します。たとえば、次のようにコンパイルしても問題ありません。

trait GraphOps { type E; type V } 
trait WeightedGraphOps extends GraphOps { def f(e: E) } 
trait DirectedGraphOps extends GraphOps { def e: E } 
object GraphOps{ 
    def Dijkstra[V0, G <: (WeightedGraphOps{type V = V0}) with (DirectedGraphOps{type V = V0})] (graph:G, start:V0) = { 
    graph.f(graph.e) 
    } 
} 
+0

これは私を助けてくれました、ありがとう!エッジタイプの制約がないことを心配する必要があるかどうかはわかりません。おそらく何か不足していますが、両方のOpsタイプで異なるEタイプを混在させるオブジェクトを作成することに失敗しています。それも可能ですか? – Dylan

+0

興味深い。タイプのダイヤモンド問題(http://en.wikipedia.org/wiki/Diamond_problem)のように聞こえます。値に関して、Scalaのダイアモンド問題への解決は、線形化スキームに基づいて、一方の値が他方の値を上書きすることです。タイプに関して、私はこれが矛盾を避けることを許されないことに驚くことではない。 –

2

は、なぜEdgeことになっていますか? Dijkstraの宣言を見ると、E(graph:G, start:V)を参照するパラメータがないことがわかります。だからスカラはGとなっていて、何がVであるはずなのかという手がかりを持っています。 Eを参照するパラメータはありません。

+0

しかし、このコールサイトでは、Scalaコンパイラを十分に巧妙に理解できませんでしたか? 'graph'の型が' WeightedGraphOps [Position、Edge] with ... 'であることを知っていると、 'E'が型を動作させるために必要なものが基本的に修正されています。 –

+0

これは、それがGraphMapの辺のタイプなので、「Edge」とされています。ダイクストラの実装にはタイプが必要なので、私はそれを放棄することはできません。 – Dylan

+0

@Dylan問題があることを理解していますが、タイプ推論の制約をよりよく理解できるようにしようとしているので、コードをより簡単に記述できます。ここでの問題は、型がパラメータから推定されることです。 'G'は' graph'から推論されます。 'E'パラメータは何から推測されるのですか?これは型制約から推測されるものではなく、それがチェックされたものだけから推定されます。 –

関連する問題