好的,对不起,我误解了你的问题无论如何,我尝试了你的代码,它看起来很有趣,但是因为我喜欢简单,所以我试图为你的问题想出一个更简单的解决方案。
object Sign {
case object Pos extends Sign
case object Neg extends Sign
case object Zero extends Sign
case object Undefined extends Sign
case object NonPos extends SignSet(Set(Neg, Zero)) {
override def toString = "NonPos"
}
case object NonNeg extends SignSet(Set(Pos, Zero)) {
override def toString = "NonNeg"
}
case object NonZero extends SignSet(Set(Pos, Neg)) {
override def toString = "NonZero"
}
case object AnySign extends SignSet(Set(Pos, Neg, Zero)) {
override def toString = "AnySign"
}
private val signs = List(Pos, Neg, Zero, Undefined, NonPos, NonNeg, NonZero, AnySign)
private def calc(op: Symbol, s1: Sign, s2: Sign): Sign = {
val sign = _calc(op, s1, s2)
signs.find(_ == sign).getOrElse(sign)
}
private def _calc(op: Symbol, s1: Sign, s2: Sign): Sign = (op, s1, s2) match {
case (op, set: SignSet, sign) => set.flatMap(s => _calc(op, s, sign))
case (op, sign, set: SignSet) => set.flatMap(s => _calc(op, sign, s))
case (_, Undefined, _) => Undefined
case (_, _, Undefined) => Undefined
case ('+, x, y) if x == y => x
case ('+, x, Zero) => x
case ('+, Zero, x) => x
case ('+, Pos, Neg) => SignSet(Pos, Neg, Zero)
case ('+, Neg, Pos) => SignSet(Pos, Neg, Zero)
case ('-, x, Neg) => _calc('+, x, Pos)
case ('-, x, Pos) => _calc('+, x, Neg)
case ('-, x, Zero) => x
case ('*, Zero, _) => Zero
case ('*, Pos, x) => x
case ('*, Neg, Pos) => Neg
case ('*, Neg, Neg) => Pos
case ('*, Neg, Zero) => Zero
case ('/, _, Zero) => Undefined
case ('/, x, y) => _calc('*, x, y)
}
}
sealed trait Sign {
import Sign.calc
def +(other: Sign) = calc('+, this, other)
def -(other: Sign) = calc('-, this, other)
def *(other: Sign) = calc('*, this, other)
def /(other: Sign) = calc('/, this, other)
def flatten: Sign = this
def |(other: Sign): Sign = other match {
case sign if sign == this => this
case SignSet(signs) => SignSet(signs + this)
case sign => SignSet(this, sign)
}
}
object SignSet {
def apply(signs: Set[Sign]) = new SignSet(signs)
def apply(signs: Sign*) = new SignSet(signs.toSet)
def unapply(set: SignSet) = Some(set.signs)
}
class SignSet(val signs: Set[Sign]) extends Sign {
def flatMap(f: Sign => Sign) = SignSet(signs.map(f)).flatten
override def flatten = signs.map(_.flatten).reduce(_ | _)
override def |(other: Sign) = other match {
case SignSet(otherSigns) => SignSet(otherSigns | signs)
case sign => SignSet(signs + sign)
}
override def toString = signs.mkString("SignSet(", ", ", ")")
def equals(other: SignSet) = signs == other.signs
override def equals(other: Any) = other match {
case set: SignSet => equals(set)
case _ => false
}
}
import Sign._
println(Pos / NonPos)
println(Pos + Neg)
println(NonZero * Zero)
println(NonZero / NonPos)
println(NonZero - NonZero)
println(NonZero + Zero)