scala - 使用 Scala 中的方法丰富 ADT 的类型类模式替代方案

标签 scala functional-programming typeclass algebraic-data-types

我编写了一个基本的代数数据类型,定义如下

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 herehere类型类模式是类型无关的,也许后者不太适合我的场景。

重点是,我正在努力找出一个有值(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/

相关文章:

scala - 实现观察者模式

scala - 在 Scala 中收集嵌套列表的子级的最简洁方法是什么?

java - 将包含 JSON 数组的 JSONArray 对象解析为 JSON 数组列表

scala - 给定关键字在 Scala 3 或 dotty 中如何工作?

haskell - 一个函数中的两个多态类

scala - 我很想知道 IDEA 的这个烦人的功能是什么 --- 这样我就可以将其关闭

scala - 无法实例化特征

haskell - 格雷特函数定义

list - 在没有 Maybe 的情况下在 Elm 中转置

dictionary - 如何(不安全地)将 map 反射(reflect)为约束?