是否有一种方法可以让编译器在寻找隐式证据时以某种方式考虑类型别名?
这是我要解决的问题的一个示例:
// Third party library
class Foo[T, P]
class FooOps[FTP, T] {
def apply[F[_, _], P](t: T)(implicit ev: F[T, P] =:= FTP): FTP = ???
}
type StringFoo = Foo[String, Boolean]
object StringFoo extends FooOps[StringFoo, String]
StringFoo("hello")
// Attempt to wrap the third party type but have the same ops
class WrappedFoo[FTP](val foo: FTP)
object WrappedFoo {
type F[T, P] = WrappedFoo[Foo[T, P]]
}
type WrappedStringFoo = WrappedFoo[StringFoo]
object WrappedStringFoo extends FooOps[WrappedStringFoo, String]
WrappedStringFoo("hello") // Cannot prove that F[String, P] =:= WrappedStringFoo
WrappedStringFoo[WrappedFoo.F, Boolean]("hello”) // This works
我不太了解编译器如何推断以下类型:
StringFoo("hello")
是否以某种方式使用可用隐式为F[_, _]
选择一个值?我一直认为它必须首先确定类型。
但是它对StringFoo
有效,而对WrappedStringFoo
无效。可能是因为类型参数的数量不同。
我如何获得:
WrappedStringFoo("hello")
要编译而不显式指定类型?
答案 0 :(得分:2)
尝试将必要的隐式对象添加到范围:
import scala.language.higherKinds
class Foo[T, P]
class FooOps[FTP, T] {
def apply[F[_, _], P](t: T)(implicit ev: F[T, P] =:= FTP): FTP = ???
}
type StringFoo = Foo[String, Boolean]
object StringFoo extends FooOps[StringFoo, String]
class WrappedFoo[FTP](val foo: FTP)
object WrappedFoo {
type F[T, P] = WrappedFoo[Foo[T, P]]
//implicit val ev0: WrappedFoo.F[String, Boolean] =:= WrappedStringFoo = ???
implicit val ev0: WrappedFoo.F[String, Boolean] =:= WrappedStringFoo =
null.asInstanceOf[WrappedFoo.F[String, Boolean] =:= WrappedStringFoo]
}
type WrappedStringFoo = WrappedFoo[StringFoo]
object WrappedStringFoo extends FooOps[WrappedStringFoo, String]
WrappedStringFoo("hello")
当您进行StringFoo("hello")
编译器求解方程F[String, P] = Foo[String, Boolean]
时,它很聪明,可以推论P = Boolean
,F = Foo
。但是,当您执行WrappedStringFoo("hello")
编译器必须求解方程F[String, P] = WrappedFoo[Foo[String, Boolean]]
时,编译器所使用的算法不足以推论P = Boolean
,F = ({ type λ[A, B] = WrappedFoo[Foo[A, B]] })#λ
即WrappedFoo.F
(甚至可能是这样)一般而言,如果方程式足够高级,则无法求解。因此,您应该提供一个提示。明确指定类型参数或提供必要的隐式证据。
解析隐式和类型推断会相互影响。您可以阅读Eugene Burmako的thesis的第4.4.3节。