我编写了一个基本的代数数据类型,定义如下
sealed trait Fruit {def name: String}
case class Apple(name: String) extends Fruit
case class Orange(name: String, color: String) extends Fruit
我想做的是定义 Apple 和 Orange 之间的通用方法。所以我决定通过类型类模式提供此功能。
sealed trait ServingFruit[T] {
def peel(fruit: T): String
}
object FruitManager {
def retrievePeelColor[T: ServingFruit](fruit: T): String =
implicitly[ServingFruit[T]].peel(fruit)
implicit object ApplePeelColor extends ServingFruit[Apple] {
def peel(fruit: Apple): String = "GREEN"
}
implicit object OrangePeelColor extends ServingFruit[Orange] {
def peel(fruit: Orange): String = fruit.color
}
}
对于必要的(不幸的)约束,我必须将水果作为共享基本特征的有界实例来处理 Fruit
def myCodeMethod[F <: Fruit](fruit: F, out: String) = {
import FruitManager._
FruitManager.retrievePeelColor(fruit)
}
这给我带来了以下(不知何故预期的)异常。
could not find implicit value for evidence parameter of type my.path.to.fruit.ServingFruit[F] [error]FruitManager.retrievePeelColor(fruit)
那么,AFAIU here和 here类型类模式是类型无关的,也许后者不太适合我的场景。
重点是,我正在努力找出一个有值(value)的解决方案,将我的 ADT 与也可用于基本特征的通用方法集成,同时,我想避免在 ADT 中提供方法(我会尝试保持 FP 导向)并使用此类解决方法,例如向我的类型类添加额外的 Fruit
转换器。
如有任何帮助,我们将不胜感激,谢谢。
安德里亚
最佳答案
您需要将类型类见证作为隐式参数传递给 retrievePeelColor
:
scala> def retrievePeelColor[T](fruity: T)(implicit peeler: ServingFruit[T]) = peeler.peel(fruity)
retrievePeelColor: [T](fruity: T)(implicit peeler: ServingFruit[T])String
scala> retrievePeelColor(Apple("granny smith"))
res0: String = GREEN
scala> retrievePeelColor(Orange("bloody", "RED"))
res1: String = RED
至于设计:我不是一个经验丰富的设计人员,但我不会说在 sealed Trait
中拥有一些方法不是“FP 风格”。如果只有水果是可剥皮的,而且数量有限,那么有一个地方可以剥皮,恕我直言(通过这个我正在讨论 Fruit
中的一种方法,与this
,或 Fruit
伴随对象中的静态成员)。
关于scala - 使用 Scala 中的方法丰富 ADT 的类型类模式替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44832249/