Scala 中的容器代数数据类型

Container Algebraic Data Type in Scala

不是很熟悉 Scala 的类型系统,但这是我正在尝试做的事情。

我有一个尝试按名字和姓氏过滤人员的功能,如果失败则只按名字过滤。

case class Person(id: Int, first: String, last:String)
def(people: Set[Person], firstName: String, lastName: String): (MatchResult, Set[Person]) =
  val (both, firstOnly) = people.filter(_.first == firstName).partition(_.last == lastName)

  (both.nonEmpty, firstOnly.nonEmpty) match {
    case (true, _) => (BothMatch, both)
    case (false, true) => (FirstOnly, firstOnly)
    case (_, _) => (NoMatch, Set[Person]())
  }

现在我返回过滤后的 Set 以及一个代数数据类型,通知调用者使用了哪个过滤器的结果。

sealed trait MatchResult
case object BothMatch extends MatchResult
case object FirstOnly extends MatchResult
case object NoMatch extends MatchResult

但是,返回 Set + MatchResult 的元组对于调用者来说并不是一个很好的契约。我想知道如何将过滤后的结果 存储在 我的 MatchResult.

我想我可以简单地更改为:

sealed trait MatchResult extends Set[People]
case object BothMatch extends MatchResult
case object FirstOnly extends MatchResult
case object NoMatch extends MatchResult 

但是编译器告诉我 must implement abstract member iterator: Iterator[A]

我不确定我是否应该尝试扩展 Set 或以某种方式使 MatchResult 成为一个将集合作为构造函数参数的 case class

一种方法是使用 case classes 将任何匹配项存储为成员。

sealed trait MatchResult
case class BothMatch(results:Set[Person]) extends MatchResult
case class FirstOnly(results:Set[Person]) extends MatchResult
case object NoMatch extends MatchResult 

在 Scala 中,Set is is trait that has abstract members 必须由任何实现 class 实现,这就是您收到该错误的原因。

在您的实施中,您可以通过

使用这些 classes
(both.nonEmpty, firstOnly.nonEmpty) match {
    case (true, _) => BothMatch(both)
    case (false, true) => FirstOnly(firstOnly)
    case (_, _) => NoMatch
  }