我写了一个基本的代数数据类型,定义如下
sealed trait Fruit {def name: String}
case class Apple(name: String) extends Fruit
case class Orange(name: String, color: String) extends Fruit
我喜欢做的是定义Apple和Orange的通用方法。所以我决定通过Type Class模式提供这个功能。
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类型类模式是独立的类型,也许后者不适合我的场景。
重点是我正在努力找出一个有价值的解决方案,将我的ADT与基本特征的常用方法结合起来 - 同时 - 我想避免在ADT中提供方法(我试图保持FP导向)并使用这样的变通方法向我的Type类添加一个额外的Fruit
转换器。
非常感谢任何帮助,谢谢。
安德烈
答案 0 :(得分:2)
您需要将类型类见证传递给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
中有一些方法不是&#34; FP风格& #34 ;.如果只有水果是可剥离的,并且数量有限,那么peel
,恕我直言就可以有一个地方(由此我在谈论Fruit
匹配的方法this
,或Fruit
随播广告对象中的静态成员。