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

Lan*_*dei 9 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])  //???
    }
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,但我需要输入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))
  }
}
Run Code Online (Sandbox Code Playgroud)

但当然这是对Bar的可能性的严重限制,所以我仍然希望得到更好的答案.

ret*_*nym 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)) //???
  }
}
Run Code Online (Sandbox Code Playgroud)

有趣的是,这并没有推断,尽管它表达了同样的事情:

def test[T, C[_], D <: C[T]](c: D)(implicit bar: Bar[C]) = ()
Run Code Online (Sandbox Code Playgroud)

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


Dan*_*ral 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))
    }
}
Run Code Online (Sandbox Code Playgroud)