Scala 如何进行密封特性的排序?

Scala 如何进行密封特性的排序?,scala,traits,enumeration,comparable,partial-ordering,Scala,Traits,Enumeration,Comparable,Partial Ordering,我有一个由某种“状态机”(“流程图”)定义的分布式系统 每个系统在共享的“日志”中写入这些状态 我将每个状态表示为一个封闭特征的一部分,以及该状态的一个给定“状态” 我想“合并/减少”到表示当前进度的单个状态 (由于并非所有人都必须成功才能成功完成最终状态,因此有一些放松措施) 有2个密封特性代表流量: sealed trait System case object A extends System case object B extends System case object C exten

我有一个由某种“状态机”(“流程图”)定义的分布式系统

每个系统在共享的“日志”中写入这些状态

我将每个状态表示为一个封闭特征的一部分,以及该状态的一个给定“状态”

我想“合并/减少”到表示当前进度的单个状态

(由于并非所有人都必须成功才能成功完成最终状态,因此有一些放松措施)

有2个密封特性代表流量:

sealed trait System
case object A extends System
case object B extends System
case object C extends System
...

sealed trait Status
case object Pending extends Status
case object InProgress extends Status
case object Success extends Status
case object Fail extends Status
日志:

现在,我使用一组规则来定义单个状态缩减

基本上,它给予优先权

A

Pending

因此,如果存在以下状态:

(A,成功)
(C,待定)

我想把它减少到
(C,待定)

如果

(A,成功)
(B,失败)

我想把它减少到
(B,失败)

在我的例子中,我可以将其建模为一个简单的整数比较(可能使用我显式测试的异常值)

我不清楚如何使这些封闭的特征易于比较/有序,从而使我的生活方式更容易

这样做就足够了:

def reduce(states: Seq[(System,Status)]) : (System,Status) = {
    states.order... {left.system < right.system) && (a.status < b.status) ... possibly another ordering test ....}.tail // take the last one in the ordering
}
def reduce(状态:Seq[(系统,状态)]:(系统,状态)={
states.order…{left.system
您可以定义一个
scala.math.Ordering[状态]

object StatusOrdering extends Ordering[Status] {
  def compare(x: Status, y: Status): Int =
    (x, y) match {
      // assuming that the ordering is Pending < InProgress < Success < Fail...
      case (_, _) if (x eq y) => 0
      case (Pending, _) => -1
      case (_, Pending) => 1
      case (InProgress, _) => -1
      case (_, InProgress) => 1
      case (Success, _) => -1
      case (_, Success) => 1
      case _ => 0 // (Fail, Fail)
    }

您的
状态
对象将被
丰富,一种方法是在两个
映射中定义
系统
状态
的优先级,然后通过
排序定义
(系统,状态)

val syMap: Map[System, Int] = Map(A->1, B->2, C->3)
val stMap: Map[Status, Int] = Map(Pending->1, InProgress->2, Success->3, Fail->4)

implicit val ssOrdering: Ordering[(System, Status)] =
  Ordering.by{ case (sy, st) => (syMap.getOrElse(sy, 0), stMap.getOrElse(st, 0)) }

import ssOrdering._

(A, Success) < (C, Pending)
// res1: Boolean = true

(A, Success) < (B, Fail)
// res2: Boolean = true

(C, Pending) < (B, Fail)
// res3: Boolean = false
考虑使用枚举数方法来定义顺序

import cats.Order
import enumeratum.values._
import cats.instances.int._

sealed abstract class Status(val value: Int) extends IntEnumEntry

object Status extends CatsOrderValueEnum[Int, Status] with IntEnum[Status] {
  case object Pending    extends Status(1)
  case object InProgress extends Status(2)
  case object Success  extends Status(3)
  case object Fail  extends Status(4)

  val values = findValues
}

object AdtOrder extends App {
  import Status._
  println(Order[Status].compare(Pending, Fail))
}
哪个输出

-1
在哪里


如果我有一系列的对象,我不明白我现在如何使用它
val syMap: Map[System, Int] = Map(A->1, B->2, C->3)
val stMap: Map[Status, Int] = Map(Pending->1, InProgress->2, Success->3, Fail->4)

implicit val ssOrdering: Ordering[(System, Status)] =
  Ordering.by{ case (sy, st) => (syMap.getOrElse(sy, 0), stMap.getOrElse(st, 0)) }

import ssOrdering._

(A, Success) < (C, Pending)
// res1: Boolean = true

(A, Success) < (B, Fail)
// res2: Boolean = true

(C, Pending) < (B, Fail)
// res3: Boolean = false
def ssReduce(ss: Seq[(System, Status)])(implicit ssOrd: Ordering[(System, Status)]) : (System, Status) = {
  import ssOrd._
  ss.reduce((acc, t) => if (t < acc) acc else t )  // Or simply `ss.max`
}

ssReduce(Seq((A, Success), (C, Pending), (B, Fail)))
// res4: (System, Status) = (C,Pending)
import cats.Order
import enumeratum.values._
import cats.instances.int._

sealed abstract class Status(val value: Int) extends IntEnumEntry

object Status extends CatsOrderValueEnum[Int, Status] with IntEnum[Status] {
  case object Pending    extends Status(1)
  case object InProgress extends Status(2)
  case object Success  extends Status(3)
  case object Fail  extends Status(4)

  val values = findValues
}

object AdtOrder extends App {
  import Status._
  println(Order[Status].compare(Pending, Fail))
}
-1
libraryDependencies ++= Seq(
  "com.beachape" %% "enumeratum" % "1.5.13",
  "com.beachape" %% "enumeratum-cats" % "1.5.15"
)