8

私はいくつかの関数を持っていますが、その唯一のパラメータ要件は、拡張可能なある種のコレクション (つまり、Queue、List、PriorityQueue など) を持つことです。そのため、次の型エイリアスを作成しようとしました。

type Frontier = Growable[Node] with TraversableLike[Node, Frontier]

次のような関数定義で使用します。

def apply(frontier: Frontier) = ???

しかし、型エイリアスは「フロンティア型を含む不正な循環参照」というエラーを返します。タイプエイリアスまたはそれに類似したものを使用するために、不正な循環参照を回避する方法はありますか?

1 つの解決策は、次を使用することです。

def apply[F <: Growable[Node] with TraversableLike[Node, F]](f: F) = ???

しかし、関数定義が型エイリアスとまったく同じことをしているように見える場合、これは不必要な冗長性を追加するようです。この型は他の場所でも使用されるため、型エイリアスを使用すると読みやすさが大幅に向上します。

4

1 に答える 1

7

仕様のセクション 4.3 から:

定義 (§4) と型パラメーター (§4.6) のスコープ規則により、型名がそれ自体の境界または右側に現れることが可能になります。ただし、型エイリアスが定義済みの型コンストラクター自体を再帰的に参照する場合は、静的エラーです。

いいえ、これを直接行う方法はありませんが、型エイリアスの型パラメーターを使用して、ほぼ同じことを実現できます。

type Frontier[F <: Frontier[F]] = Growable[Int] with TraversableLike[Int, F]

今、あなたは次のapplyように書くだけです:

def apply[F < Frontier[F]](frontier: F) = ???

仮定の最初のバージョンよりもまだ少し冗長ですが、すべてを書き出すよりは短くなります。

存在タイプにワイルドカードの短縮形を使用することもできます。

type Frontier = Growable[Node] with TraversableLike[Node, _]

これで、最初のものapply がそのまま機能します。そのスロットに適合するタイプが必要だと言っているだけですがそれが何であるかは気にしません。

この場合、具体的には、Traversable[Node]代わりに使用しない理由はありますか? 実質的に同じことを達成し、その表現型でパラメーター化されていません。

于 2012-11-20T22:58:05.450 に答える