在scala中为强类型状态机发出具有不同类型参数的继承特征

时间:2014-03-19 20:15:07

标签: scala

我正在尝试在当前应用程序的上下文中创建状态机。以下是我想要做的一个例子。

我已经定义了一系列状态,这些状态随着应用程序的增长而增长,并且单个状态可以转换为任意数量的其他特征(例如,A可以转换为B,C或D)。我希望能够在所有状态上进行模式匹配,以便编译器在我错过任何状态时发出警告。

sealed trait State {
  val name: String
}

// can transition to B or C
case class StateA(data: String) extends State{
  val name = "A"
}

// can transition to C
case class StateB(data: String) extends State with BuiltFrom[StateA]{
  val name = "B"
}

/*
 *  ISSUE: class StateC inherits different type instances of trait BuiltFrom: BuiltFrom[StateB] and BuiltFrom[StateA]
 */
case class StateC(data: String) extends State with BuiltFrom[StateA] with BuiltFrom[StateB]{
  val name = "C"
}

sealed trait BuiltFrom[-State]

// Attempted to use these
// sealed trait FromA extends BuiltFrom[StateA]
// sealed trait FromB extends BuiltFrom[StateB]

我试图使用BuiltFrom特性来定义可能的转换。它的目的是允许编译器阻止我定义无效的Transition,并在我对转换结果进行模式匹配时确认我,以确定我们现在处于什么状态(而不是仅匹配所有状态)匹配可能状态的子集。)

abstract class Transition[S <: State, V](state: S) {

  // Abstract member to define the transition
  protected def trans(s: S, v: V): BuiltFrom[S]

  // syntactical sugar
  def transition(v: V): BuiltFrom[S] = trans(state, v)

}

上面我已经定义了转换,对于任何状态S,唯一可以返回的新状态必须是BuiltFrom [S]类型。我也接受进行转换所需的一些数据(通常是POST表单数据)。

case class PostedFormData(data: String)

case class TransitionA(a: StateA) extends Transition[StateA, PostedFormData](a) {

  def trans(state: StateA, formData: PostedFormData) = {
    if (formData.data.length > 0 ){ // for the sake of an example condition
      StateB(formData.data)
    }
    else{
      StateC(formData.data)
    }
  }
}
object TransitionA{

  implicit def stateAToTransitionA(s: StateA): TransitionA = TransitionA(s) // implicit conversion

}

上面是一个示例Transition。我希望能够返回一个类型为BuiltFrom [StateA]的状态。

object Controller {

  // Example usage
  def action(state: StateA) = {

    val form_data = PostedFormData("Some Data")
    val new_state: BuiltFrom[StateA] = TransitionA.stateAToTransitionA(state).transition(form_data) // why will the implicit conversion not work here?

    // Extract the new state
    new_state match {
      case b: StateB => {"B"}
      case c: StateC => {"C"}
    }
  }

以上是我想在控制器级别使用转换代码的方法。理想情况下,隐式转换应该有效,但重要的是我可以对返回的状态进行模式匹配,以确定我所处的新状态。

我遇到的问题是可以从多个州过渡到的州。我收到以下错误:

  

类StateC继承特性的不同类型实例BuiltFrom:BuiltFrom [StateB]和BuiltFrom [StateA]

我想知道是否有办法可以解决这个问题。或者,我愿意接受重新设计的建议,以实现相同的目标(尽可能利用编译器的优势)。

谢谢!

1 个答案:

答案 0 :(得分:0)

我建议您不要尝试使用自己的有限状态机,而是检查一些现有的选项: