加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 从非协方差的实例创建协变类型类的实例

发布时间:2020-12-16 09:31:21 所属栏目:安全 来源:网络整理
导读:假设我有一个简单的类型类,其实例会给我一些类型的值: trait GiveMeJustA[X] { def apply(): X } 我有一些实例: case class Foo(s: String)case class Bar(i: Int)implicit object GiveMeJustAFoo extends GiveMeJustA[Foo] { def apply() = Foo("foo")}i
假设我有一个简单的类型类,其实例会给我一些类型的值:

trait GiveMeJustA[X] { def apply(): X }

我有一些实例:

case class Foo(s: String)
case class Bar(i: Int)

implicit object GiveMeJustAFoo extends GiveMeJustA[Foo] {
  def apply() = Foo("foo")
}

implicit object GiveMeJustABar extends GiveMeJustA[Bar] {
  def apply() = Bar(13)
}

现在我有一个类似(但不相关)类型的类,它的类型参数是相同的,但是是一致的:

trait GiveMeA[+X] { def apply(): X }

在其配套对象中,我们告诉编译器如何从非协变类型类的实例创建实例:

object GiveMeA {
  implicit def fromGiveMeJustA[X](implicit giveMe: GiveMeJustA[X]): GiveMeA[X] =
    new GiveMeA[X] { def apply() = giveMe() }
}

现在我会暗示[GiveMeA [Foo]]编译很好,因为只有一种方法可以得到一个GiveMeA [Foo],因为我们在这里提供的部分。但它不(至少不在2.10.4或2.11.2):

scala> implicitly[GiveMeA[Foo]]
<console>:16: this.GiveMeA.fromGiveMeJustA is not a valid implicit value for GiveMeA[Foo] because:
hasMatchingSymbol reported error: ambiguous implicit values:
 both object GiveMeJustAFoo of type GiveMeJustAFoo.type
 and object GiveMeJustABar of type GiveMeJustABar.type
 match expected type GiveMeJustA[X]
              implicitly[GiveMeA[Foo]]
                        ^
<console>:16: error: could not find implicit value for parameter e: GiveMeA[Foo]
              implicitly[GiveMeA[Foo]]
                        ^

如果我们摆脱了我们不相关的GiveMeJustA实例,它的工作原理是:

scala> implicit def GiveMeJustABar: List[Long] = ???
GiveMeJustABar: List[Long]

scala> implicitly[GiveMeA[Foo]]
res1: GiveMeA[Foo] = GiveMeA$$anon$1@2a4f2dcc

尽管如此,我们无法将GiveMeA.fromGiveMeJustA应用到此实例以获取GiveMeA [Foo](或GiveMeA [Foo]的任何子类型)的事实。

这看起来像是一个bug,但是我可能会丢失一些东西。这是否有意义?有合理的解决方法吗?

解决方法

我不明白为什么它的工作,但以下代码在当前的情况下成功解析隐藏(至少在scala v-2.10.1)。但是,这还没有解释为什么你的例子首先不起作用:

我们更改隐式的GiveMeA [X]实例来搜索隐藏的GiveMeJustA实例,其中类型参数向上限定X,从而搜索GiveMeJustA [_<:X]

object GiveMeA {
  implicit def fromGiveMeJustA[X](implicit giveMe: GiveMeJustA[_ <: X]) : GiveMeA[X] =
    new GiveMeA[X] { def apply() = giveMe() }
}

然后,我们可以打印出预期的输出

val a = implicitly[GiveMeA[Foo]]
println(a()) // prints "Foo(foo)"

但是,一旦我们引入了一个新的子类

case class FooChild(s: String) extends Foo(s)

和各自的GiveMeJustA类型实例

implicit object GiveMeJustAFooChild extends GiveMeJustA[FooChild] {
    def apply() = FooChild("fooChild")
}

编译器抱怨(如预期)

error: could not find implicit value for parameter e: GiveMeA[Foo]
    val a = implicitly[GiveMeA[Foo]]

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读