我尝试使用隐式实现匹配类型,这里是一个工作示例:
{
trait FnUnpack[F <: Function1[?, ?]] {
type II
type OO
}
object FnUnpack {
implicit def only[I, O]: FnUnpack[I => O] { type II = I; type OO = O } =
null
}
val u = summon[FnUnpack[Int => String]]
summon[u.II =:= Int]
}
字符串
但是稍微改变一下,使它更容易被Function 1的子类接受,我可以很容易地打破它:
{
trait FnUnpack[-F <: Function1[?, ?]] {
type II
type OO
}
object FnUnpack {
implicit def only[I, O]: FnUnpack[I => O] { type II = I; type OO = O } =
null
}
val u = summon[FnUnpack[Int => String]]
summon[u.II =:= Int]
//[Error] XXX.scala:36:11: Cannot prove that u.II =:= Int.
}
型
如果启用了splain插件,编译器会自动假定u.II = Nothing
Nothing (reduced from) { u.II } =:= Int
Cannot prove that u.II =:= Int.
型
看起来,一个逆变标记完全破坏了隐式搜索算法!这是怎么发生的,需要做些什么来修复它?
1条答案
按热度按时间lsmd5eda1#
为了使
FnUnpack
更容易被Function1
的子类接受,而不破坏隐式解析机制,您可以使用隐式定义中的类型绑定,而不是将方差应用于trait本身。这样,隐式示例可以更灵活地接受什么,而不会影响类型成员的推断。字符串
**更新:**对于Scala 2,类型推断不如Scala 3强大,我们需要为编译器提供更多指导。这里的挑战是Scala 2的类型推断在此特定上下文中难以推断类型成员。
一种解决方法是使用带有类型参数而不是类型成员的类型类。
型