如何描述和修复此Scala类型不匹配错误?
下面是我有时遇到的参数化类型的一种情况的具体实例。基本上,我知道有些类型参数是兼容的,但我不知道如何在代码的某些部分证明这一点 我正在编写一个请求路由器,它将URL映射到处理程序函数。下面是一些简化的代码。我创建了一个如何描述和修复此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]
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)
}