虽然使用shapeless和kind-projector在代码中捕获了此问题,但可以在没有它们的情况下重现此行为。
假设我有一个简单的类型类来重新实现具有不完整实现的类型类实例(镜像LiftAll
)。
sealed trait LiftAll1[F[_], In] {
type Out
def instances: Out
}
object LiftAll1 {
type Aux[F[_], In0, Out0] = LiftAll1[F, In0] {type Out = Out0}
implicit def unit[F[_]]: Aux[F, Unit, Unit] = new LiftAll1[F, Unit] {
type Out = Unit
def instances = Unit
}
}
还有一些非常简单的类型来测试它
sealed class FirstIs[M, T]
object FirstIs {
implicit def firstIs[M, D]: FirstIs[M, (M, D)] = new FirstIs
}
如果我尝试通过别名部分应用FirstIs
,并通过LiftAll1
type FirstIsInt[D] = FirstIs[Int, D]
implicitly[LiftAll1[FirstIsInt, Unit]]
但内联的部分类型应用程序会导致编译错误
implicitly[LiftAll1[({type lambda[x] = FirstIs[Int, x]})#lambda, Unit]]
//Error: could not find implicit value for parameter e: LiftAll1[[x]FirstIs[Int,x],Unit]
在这种情况下如何找到部分应用的类型类?
答案 0 :(得分:0)
正如@Reactormonk建议的那样,编译器was brought to its senses在build.sbt
scalacOptions += "-Ypartial-unification"
在原始代码之后,接近
import shapeless._, ops.hlist._
LiftAll[FirstIs[Int, ?], HNil]
成功编译
AFAIK问题是scala编译器无法在没有直接类型别名的情况下将FirstIs[Int,_]
理解为提供的F[_]
中的implicit def
。幸运的是,这已在最新的scala实现中得到修复。