以下は、パラメータ化された型で時々遭遇する状況の特定の例です。基本的に、互換性があることがわかっている型パラメーターがありますが、コードの一部でそれを証明する方法がわかりません。
URLをハンドラー関数にマップするリクエストルーターを書いています。以下は単純化されたコードです。List[Route]
aRoute
が基本的にUrlMatcher, Function
ペアである aを作成します。
class Route[A](matcher: UrlMatcher[A], handler: HandlerFunction[A])
abstract class UrlMatcher[A] {
def match(url: String): Option[A] // None if no match
type パラメーターA
は、マッチャーが URL から抽出する「引数」用です。それらはハンドラ関数に渡されます。たとえば、UrlMatcher[Int]
「/users/123」のような URL パスを参照する は、getUser(id: Int)
関数に 123 を渡すことができます。ルーターは次のようになります。
val routes = ArrayBuffer[Route[_]]
def callHandler(url: String) {
for (r <- routes) {
val args = r.matcher.matchUrl(url)
if (args.isDefined)
r.handler(args.get) // <--- error here
}
問題は、2 つの型が同じであることを伝える方法がわからないため、型の不一致エラーが発生することです。
type mismatch; found: args.type (with underlying type Option[Any])
required: _$1
Route
のようなメソッドを持つように再設計できることはわかっていますmatchAndCall
が、可能であればこの論理フローを維持したいと考えています。
更新/編集
私は存在型を完全には理解していませんが、これを試しました...
val routes = ArrayBuffer[T forSome { type T }]()
そして、上記の不一致エラーを削除しました。ただし、に挿入していた別のものがありArrayBuffer
ます。
def route[P](matcher: UrlMatcher[P], handler: Handler[P]): AbstractRoute = {
val route = new Route(matcher, handler)
otherRoutes.append(route) // error here
route
}
今、エラーは...
type mismatch; found : Route[P] required: Route[T forSome { type T }] Note: P <: T
forSome { type T }, but class Route is invariant in type P. You may wish to define
P as +P instead. (SLS 4.5)
には制約がないのに、とP
互換性がないのはなぜですか?T
T