2

以下は、パラメータ化された型で時々遭遇する状況の特定の例です。基本的に、互換性があることがわかっている型パラメーターがありますが、コードの一部でそれを証明する方法がわかりません。

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互換性がないのはなぜですか?TT

4

1 に答える 1