请考虑以下代码:
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进行测试?
[澄清]
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的可能性有严重限制,所以我仍然希望得到更好的答案。
答案 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))
}
}