较高kinded类型的隐式参数解析

时间:2010-09-28 19:18:13

标签: scala implicit higher-kinded-types

请考虑以下代码:

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])。有没有办法避免显式输入,所以我在测试中得到隐含的OptionBar对象,即使我使用Some或None进行测试?

[澄清]

  • 我在这里使用Option作为示例,如果我有一个Bar用于抽象类等,它也应该有效。
  • 当其他不相关的条在范围内时,解决方案也应该有效,比如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的可能性有严重限制,所以我仍然希望得到更好的答案。

2 个答案:

答案 0 :(得分:7)

它并不适用于所有情况,但如上所述,你可以试试这个:

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]) = ()

要详细了解<:<,请参阅:

答案 1 :(得分:5)

这是因为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))
    }
}