我曾尝试在 Scala 中实现 StateMachine,但是我遇到了类型系统的问题,这让我很困惑。在下面的代码中,我需要让守卫函数接受一个预期的 StateMachine 子类的参数。不幸的是,由于FunctionN参数的类型参数是逆变的,我不知道如何解决这个问题。
类转换[S,+M <:StateMachine[S]](开始:S,结束:S,var guard:Option[M => Boolean]){
// 上面的编译器错误:^^ 协变类型 M 出现在方法保护的 type => Option[M => Boolean] 的逆变位置 ^^
val startState = 开始
val endState = 结束
def willFollow(stateMachine: M, withGuard: Boolean) =
// 上面的编译器错误:^^ 协变类型 M 出现在值 stateMachine 的类型 M 的逆变位置 ^^
if (!withGuard && guard == None) true;
否则(withGuard && guard.get(stateMachine))
}
类 EpsilonTransition[S, M <: StateMachine[S]](start: S,end :S) extends Transition[S, M](start, end, None)
类StateMachine[S](转换:Set[Transition[S,StateMachine[S]]],initialStates:Set[S]){
私人 val stateDrains = transitions.groupBy(_.startState);
私有 var activeStates = initialStates
默认行为() = {
var entryStates = Set[S]()
var exitStates = Set[S]()
stateDrains.foreach {排水 =>
val (exitState, transitionsOut) = drain
// 跟随非 epsilon 转换
transitionsOut.filter(_.willFollow(this, true)).foreach {transition =>
exitStates += transition.startState
entryStates += transition.endState
}
}
// 对于所有退出状态,我们将状态映射到一组转换,并且所有集合都“扁平化”为一个大的转换集
// 然后它将被那些没有保护的过滤器(epsilon 转换)。生成的过滤转换列表
// 所有都包含我们将映射到的 endStates。所有这些结束状态都附加到当前的入口状态集。
entryStates = entryStates ++ (exitStates.flatMap(stateDrains(_)).filter(_.willFollow(this, false)).map(_.endState))
// 只排除我们没有重新进入的退出状态
// 然后包括新进入的状态
activeStates = ((activeStates -- (exitStates -- entryStates)) ++ entryStates)
}
覆盖 def toString = activeStates.toString
}
对象 HvacState 扩展枚举 {
类型 HvacState = 值
val 空调、加热器、风扇 = 值
}
导入 HvacState._
对象 HvacTransitions {
val autoFan = new EpsilonTransition[HvacState, HVac](空调, 风扇)
val turnOffAc = new Transition[HvacState, HVac](空调, 风扇, Some(_.temperature 75))
val HeaterToFan = new Transition[HvacState,Hvac](加热器、风扇、一些(_.temperature > 50))
}
导入 HvacTransitions._
HVac 类扩展 StateMachine[HvacState](Set(autoFan, turnOffAc, AcToHeater, HeaterToAc, HeaterToFan), Set(heater)) {
变量温度 = 40
}