gpt4 book ai didi

scala - 如何在隐式搜索期间自动剥离 Scala 特征?

转载 作者:行者123 更新时间:2023-12-01 13:16:09 25 4
gpt4 key购买 nike

我正在使用类型类,但在为不相关地扩展额外(标记/指示器)特征的类型自动派生它们时遇到问题。这很难解释,但这个最小的例子应该清楚我的意思:

// 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 上的类型推断正在崩溃,因为当编译器正在寻找 IsHarmfulToEat[Cake with Plentiful] 时,ignoreSupply 根本没有尝试使用正确的类型。谁能向我解释为什么会这样?和/或如何引导编译器尝试正确的类型?和/或以另一种方式实现 ignoreSupply 规则?

最佳答案

如果你使 IsHarmfulToEat 逆变以下代码编译

  trait Food

trait Plentiful

trait IsHarmfulToEat[-F <: Food]

object IsHarmfulToEat {
implicit def ignoreSupply[F <: Food]
(implicit isHarmful: IsHarmfulToEat[F]
): IsHarmfulToEat[F with Plentiful] =
new IsHarmfulToEat[F with Plentiful]{}
}

case class Cake() extends Food {}

object Cake {
implicit val isBad: IsHarmfulToEat[Cake] = new IsHarmfulToEat[Cake] {}
}

object FoodTest extends App {
val ignoreSupplyDoesWork: IsHarmfulToEat[Cake with Plentiful] =
IsHarmfulToEat.ignoreSupply[Cake]

val badCake = implicitly[IsHarmfulToEat[Cake]]
val manyBadCakes = implicitly[IsHarmfulToEat[Cake with Plentiful]]
}

关于scala - 如何在隐式搜索期间自动剥离 Scala 特征?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54795247/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com