我正在使用类型类,并且在自动派生类型时遇到了问题,这些类型没有延迟地扩展了额外的(标记/指示符)特性。这很难解释,但这个小小的例子应该能让我明白我的意思:
// Base type we are working on
trait Food {}
// Marker trait - unrelated to Food's edibility
trait Plentiful {}
// Indicator type class we want to derive
trait IsHarmfulToEat[F<:Food] {}
object IsHarmfulToEat {
// Rule that says that if some food is harmful to eat,
// an enormous amount is so as well
implicit def ignoreSupply[F1<:Food,F2<:F1 with Plentiful]
(implicit isHarmful: IsHarmfulToEat[F1],
constraint: F2=:=F1 with Plentiful): IsHarmfulToEat[F2] =
new IsHarmfulToEat[F2]{}
}
// Example of food
case class Cake() extends Food {}
object Cake {
// Mark Cake as being bad for you
implicit val isBad: IsHarmfulToEat[Cake] = new IsHarmfulToEat[Cake] {}
}
object FoodTest extends App {
// Our main program
val ignoreSupplyDoesWork: IsHarmfulToEat[Cake with Plentiful] =
IsHarmfulToEat.ignoreSupply[Cake,Cake with Plentiful] // compiles fine
val badCake = implicitly[IsHarmfulToEat[Cake]] // compiles fine
val manyBadCakes = implicitly[IsHarmfulToEat[Cake with Plentiful]]
// ^^^ does not compile - I do not understand why
}
(如果我做出同样的行为 Plentiful
通用和/或添加自身类型的 Food
对它来说。)
研究编译中的隐式日志,我发现:
Food.scala:33: util.this.IsHarmfulToEat.ignoreSupply is not a valid implicit value for IsHarmfulToEat[F1] because:
hasMatchingSymbol reported error: diverging implicit expansion for type IsHarmfulToEat[F1]
starting with method ignoreSupply in object IsHarmfulToEat
val manyBadCakes = implicitly[IsHarmfulToEat[Cake with Plentiful]]
^
Food.scala:33: util.this.IsHarmfulToEat.ignoreSupply is not a valid implicit value for IsHarmfulToEat[Cake with Plentiful] because:
hasMatchingSymbol reported error: diverging implicit expansion for type IsHarmfulToEat[F1]
starting with method ignoreSupply in object IsHarmfulToEat
val manyBadCakes = implicitly[IsHarmfulToEat[Cake with Plentiful]]
^
Food.scala:33: diverging implicit expansion for type IsHarmfulToEat[Cake with Plentiful]
starting with method ignoreSupply in object IsHarmfulToEat
val manyBadCakes = implicitly[IsHarmfulToEat[Cake with Plentiful]]
在我看来,f1的类型推断正在崩溃,就像 ignoreSupply
只是在编译器查找 IsHarmfulToEat[Cake with Plentiful]
. 有人能解释一下为什么吗?和/或如何引导编译器尝试正确的类型?和/或以另一种方式实现ignoresupply规则?
1条答案
按热度按时间llycmphe1#
如果你能
IsHarmfulToEat
以下代码编译