更高种类类型的隐式参数解析

发布于 2024-09-24 23:47:56 字数 989 浏览 7 评论 0原文

考虑以下代码:

object foo {

    trait Bar[Q[_]]

    implicit object OptionBar extends Bar[Option]

    def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()

    def main(args: Array[String]) {
      test(Some(42): Option[Int])  //???
    }
}

这可行,但我需要将 Some(42) 输入为 Option[Int],否则隐式对象 OptionBar 将无法解析(因为需要 Bar[Some])。有没有办法避免显式键入,以便即使我使用 Some 或 None 提供测试,我也会在测试中获得隐式 OptionBar 对象?

[澄清]

  • 我在这里使用 Option 只是作为示例,如果我有一个用于抽象类等的 Bar ,它也应该起作用。
  • 当其他不相关的 Bars 在范围内时,该解决方案也应该起作用,比如 implicit object listBar extends Bar[list]

[更新]

似乎使 Bar 的参数逆变可以解决问题:

object foo {

  trait Bar[-Q[_]] //<---------------

  implicit object OptionBar extends Bar[Option]
  implicit object ListBar extends Bar[List]

  def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()

  def main(args:Array[String]) {
    test(Some(42))
  }
}

但当然这是对 Bar 中可能性的严重限制,所以我仍然希望有一个更好的答案。

Consider the following code:

object foo {

    trait Bar[Q[_]]

    implicit object OptionBar extends Bar[Option]

    def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()

    def main(args: Array[String]) {
      test(Some(42): Option[Int])  //???
    }
}

This works, but I need to type the Some(42) as Option[Int], else the implicit object OptionBar won't be resolved (because a Bar[Some] is expected instead). Is there a way to avoid the explicit typing, so that I get the implicit OptionBar object in test even if I feed test with a Some or None?

[Clarification]

  • I used Option here just as example, it should also work if I have a Bar for an abstract class etc.
  • The solution should also work when other, unrelated Bars are in scope, say implicit object listBar extends Bar[list]

[Update]

It seems that making Bar's parameter contravariant does the trick:

object foo {

  trait Bar[-Q[_]] //<---------------

  implicit object OptionBar extends Bar[Option]
  implicit object ListBar extends Bar[List]

  def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()

  def main(args:Array[String]) {
    test(Some(42))
  }
}

But of course this is a severe limitation of the possibilities in Bar, so I still hope for a better answer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无人问我粥可暖 2024-10-01 23:47:56

它不会在所有情况下都有效,但如上所述,您可以尝试以下操作:

object foo {
  trait Bar[Q[_]]

  implicit object OptionBar extends Bar[Option]

  def test[T, C[_], D](c: D)(implicit bar: Bar[C], ev: D <:< C[T]) = ()

  def main(args: Array[String]) {
    test(Some(42)) //???
  }
}

有趣的是,这并不能推断,尽管它表达了相同的内容:

def test[T, C[_], D <: C[T]](c: D)(implicit bar: Bar[C]) = ()

要了解有关 <:< 的更多信息,请参阅:

It's not going to work in all cases, but as stated, you can try this:

object foo {
  trait Bar[Q[_]]

  implicit object OptionBar extends Bar[Option]

  def test[T, C[_], D](c: D)(implicit bar: Bar[C], ev: D <:< C[T]) = ()

  def main(args: Array[String]) {
    test(Some(42)) //???
  }
}

Interestingly, this doesn't infer, although it expresses the same thing:

def test[T, C[_], D <: C[T]](c: D)(implicit bar: Bar[C]) = ()

To learn more about <:<, see:

遗心遗梦遗幸福 2024-10-01 23:47:56

这是因为 Some(42) 是比 Option[Int] 更具体的类型。它是一个Some[Int]。请参阅下面的替代编码:

object foo {

    trait Bar[Q[_]]

    implicit object OptionBar extends Bar[Option]

    def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()

    def main(args: Array[String]) {
      test(Option(42))
    }
}

That's because Some(42) is a more specific type than Option[Int]. It is a Some[Int]. See alternative coding below:

object foo {

    trait Bar[Q[_]]

    implicit object OptionBar extends Bar[Option]

    def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()

    def main(args: Array[String]) {
      test(Option(42))
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文