考虑以下类型定义:
trait LiftF[F[_], G[_]] {
def liftF[A](fa: F[A]): G[A]
}
当在上下文边界中提供这种类型的隐式要求时(使用 kind 投影仪插件),我们必须这样写:
def func[A, G[_], F[_]: LiftF[?[_], G]](a: F[A]): G[A]
我想去掉这?[_]
部分,所以我最初的猜测是写一个To[G[_]]
返回的类型,LiftF[?[_], G]
以便将上面的函数定义转换为
def func[A, G[_], F[_]: LiftF.To[G]](a: F[A]): G[A]
但是,当将类型To
定义写为
type To[G[_]] = LiftF[?[_], G]
我收到以下编译错误:
Error:(17, 20) type Λ$ takes type parameters
type To[G[_]] = LiftF[?[_], G]
尝试用存在类型重写它会产生以下类型定义:
type To[G[_]] = LiftF[F, G] forSome { type F[X] }
这编译得很好,但不出所料,不能应用于其他类型参数,因此无法实现所需的函数定义。
我设法用受 aux 模式启发的代码实现了“部分应用程序”部分:
trait To[G[_]] {
type From[F[_]] = LiftF[F, G]
}
可悲的是,这给我留下了可以说比原始语法更糟糕的语法:
def func[A, G[_], F[_]: LiftF.To[G]#From](a: F[A]): G[A]
我的问题是 - 我可以在实物投影仪的帮助下在 Scala 中实现最初提出的语法,还是应该坚持使用?[_]
?