Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何描述和修复此Scala类型不匹配错误?_Scala_Type Systems_Type Mismatch_Existential Type_Parameterized Types - Fatal编程技术网

如何描述和修复此Scala类型不匹配错误?

如何描述和修复此Scala类型不匹配错误?,scala,type-systems,type-mismatch,existential-type,parameterized-types,Scala,Type Systems,Type Mismatch,Existential Type,Parameterized Types,下面是我有时遇到的参数化类型的一种情况的具体实例。基本上,我知道有些类型参数是兼容的,但我不知道如何在代码的某些部分证明这一点 我正在编写一个请求路由器,它将URL映射到处理程序函数。下面是一些简化的代码。我创建了一个List[Route],其中Route基本上是UrlMatcher,Function对 class Route[A](matcher: UrlMatcher[A], handler: HandlerFunction[A]) abstract class UrlMatcher[A]

下面是我有时遇到的参数化类型的一种情况的具体实例。基本上,我知道有些类型参数是兼容的,但我不知道如何在代码的某些部分证明这一点

我正在编写一个请求路由器,它将URL映射到处理程序函数。下面是一些简化的代码。我创建了一个
List[Route]
,其中
Route
基本上是
UrlMatcher,Function

class Route[A](matcher: UrlMatcher[A], handler: HandlerFunction[A])

abstract class UrlMatcher[A] {
   def match(url: String): Option[A]   // None if no match
类型参数
A
用于匹配器可能从URL提取的“参数”。它们将被传递给处理函数。例如,
UrlMatcher[Int]
看到像“/users/123”这样的URL路径可以将123传递给
getUser(id:Int)
函数。路由器可能看起来像:

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
    }
我知道我可以重新设计它,使
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) 

类型不匹配;found:Route[P]required:Route[T forSome{type T}]注意:P

这是存在类型(与通配符类型相当的Scala)是一件坏事(TM)的原因之一,在不执行Java互操作时最好避免:编译器不能(或只是不够聪明)正常地推理哪些类型等于哪些类型,因为他们都走了

要使编译器理解这些类型是相同的,您需要以某种方式为该类型命名

类型参数是一种可能性:您可以定义一个参数化的方法,该方法的内容用于理解,因此在该方法中,类型是众所周知的

def callHandler(url: String) {
  def call[T](r: Route[T]) = {
    val args = r.matcher.matchUrl(url)
    if (args.isDefined) r.handler(args.get)
    // or args.foreach(r.handler)
  }
  for (r <- routes) call(r)
  // or routes.foreach(call)
}
def调用处理程序(url:String){
def呼叫[T](r:路由[T])={
val args=r.matcher.matchUrl(url)
if(args.isDefined)r.handler(args.get)
//或args.foreach(r.handler)
}

对于(r,我理解这里的观点,但Scala的存在类型仅用于Java互操作性是不正确的(例如,Scala花费了一整条关键字,对于某些
,它在
上没有那么多)。有很多完全合法的(尽管肯定,更高级)与Java无关的使用。是的,它们比Java的通配符等(以及更古老的)更强大,但我记得Martin Odersky在某处说过,如果不是与擦除、通配符和原始类型兼容,它们就不会出现在Scala中。我不理解存在类型——比如
[t]的含义
def callHandler(url: String) {
  def call[T](r: Route[T]) = {
    val args = r.matcher.matchUrl(url)
    if (args.isDefined) r.handler(args.get)
    // or args.foreach(r.handler)
  }
  for (r <- routes) call(r)
  // or routes.foreach(call)
}