Scala 模糊含蓄

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]{

问题是为什么下面的代码不能与类型推断一起工作(下面是要演示的REPL会话),它可以被修复吗?更具体地说,这与编译器用来推断返回类型的canbuild有什么不同

鉴于此代码:

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] {