Scala 模糊含蓄
问题是为什么下面的代码不能与类型推断一起工作(下面是要演示的REPL会话),它可以被修复吗?更具体地说,这与编译器用来推断返回类型的canbuild有什么不同 鉴于此代码:Scala 模糊含蓄,scala,implicits,Scala,Implicits,问题是为什么下面的代码不能与类型推断一起工作(下面是要演示的REPL会话),它可以被修复吗?更具体地说,这与编译器用来推断返回类型的canbuild有什么不同 鉴于此代码: object S { import java.net._ trait UrlLike[T] { def url(s: String): T } object UrlLike { implicit object str extends UrlLike[String]{
object S {
import java.net._
trait UrlLike[T] {
def url(s: String): T
}
object UrlLike {
implicit object str extends UrlLike[String]{def url(s: String) = s}
implicit object url extends UrlLike[URL]{def url(s: String) = new URL(s)}
implicit object uri extends UrlLike[URI]{def url(s: String) = new URI(s)}
}
trait UrlSupport {
val _url: String
def url[T : UrlLike]: T = implicitly[UrlLike[T]].url(_url)
}
}
我在REPL(2.8.1)中有这一环节:
scala>:加载c:\temp\UrlTest.scala
正在加载c:\temp\UrlTest.scala。。。
定义模块
scala>导入java.net_
导入java.net_
scala>导入S_
进口美国_
scala>新url支持{val\u url=”http://example.com"}
res0:java.lang.Object和S.UrlSupport=$anon$1@155bd22
scala>res0.url:String
:14:错误:不明确的隐式值:
对象S.URLIKE.uri类型的对象URLIKE中的两个对象uri
以及对象S.URLIKE.url类型的对象URLIKE中的对象url
匹配预期的类型S.urlike[T]
res0.url:String
^
scala>res0.url:url
:14:错误:不明确的隐式值:
对象S.URLIKE.uri类型的对象URLIKE中的两个对象uri
以及对象S.URLIKE.url类型的对象URLIKE中的对象url
匹配预期的类型S.urlike[T]
res0.url:url
^
scala>res0.url[字符串]
res3:字符串=http://example.com
scala>res0.url[url]
res4:java.net.URL=http://example.com
关于任何隐含的歧义,以下内容:
比较重载方法或隐式方法的两个不同适用备选方案时,每个方法:
- 具有更多特定参数的得一分
- 另一点是在适当的子类中定义李>
这特别意味着,如果备选方案具有相同的参数类型,则在子类中定义的参数类型将获胜
我认为
URL
或URI
周围的隐式元素不会根据这些标准得到不同的点集。从您看到的错误报告中可能不明显,但object urlike中定义的所有三个隐式元素都会导致歧义(例如,试着注释一下uri的定义,你会看到str和url之间的歧义)
产生歧义的原因是,UrlSupport.url的类型参数T仅受以下要求的限制:它必须有一个隐式的类似UrlLike的实例可用。由于三个隐式对象提供了类似UrlLike的实例,字符串、url和URI都同样能满足这一要求。编译器不会选择其中一个这些都是为你武断,所以它报告了一个含糊不清
当然,除非您通过显式指定类型参数来解决歧义,就像您在最后两次REPL交互中所做的那样。我可以理解为什么您希望它工作,但是,很明显,类型推断器没有使用返回类型来推断
t
。我也希望如此
对于歧义,CanBuildFrom
通过不在同一“级别”中定义所有内容来避免歧义。例如,这解决了歧义问题:
trait LowPriorityImplicits {
implicit object url extends UrlLike[URL]{def url(s: String) = new URL(s)}
implicit object uri extends UrlLike[URI]{def url(s: String) = new URI(s)}
}
object UrlLike extends LowPriorityImplicits {
implicit object str extends UrlLike[String]{def url(s: String) = s}
}
但是,它不会使类型推断按您希望的方式工作:
scala> res0.url : URL
<console>:16: error: type mismatch;
found : String
required: java.net.URL
res0.url : URL
^
scala>res0.url:url
:16:错误:类型不匹配;
找到:字符串
必需:java.net.URL
res0.url:url
^
这表明它显然在不考虑返回类型的情况下进行了
T
推断。编译器没有看到由于类型归属,我想要字符串/URL/URI的结果吗?
> trait UrlLike[T] {
trait UrlLike[+T] {
> trait UrlLike[T] {
trait UrlLike[+T] {