Is there a way to pattern match from an abstract class? If I try to implement an unapply
method it will be overridden by the case classes which extend it.
I have an abstract class, Combination
which represents an AND or OR node in an expression tree. There are two subclasses (both case classes) which represent the AND and OR nodes themselves.
The Combination
class is useful as there are many operations whose code would be very similar for both the AND and OR subclasses.
One annoying limitation is that I can’t pattern match on Combination
-ness.
For example, here is a method conversion1
which does a certain symbolic logical simplification on OR (called SOr
). The same reduction should apply to SAnd
, but I need to write the dual code, I.e., replace:
- SAnd → SOr
- SOr → And
In other similar cases I need two swap the 0 and 1 of the Boolean algebra also, but doesn’t apply to this special case.
I can easily a achieve this by copying the method text into the other classes, and replacing And with Or and Or with And. However, it is bizarre that there’s no way to let the language do this for me.
For example, what should happen to the line:
val ands = tds.collect{ case td@SAnd(_*) => td}
The var ands
which has type Seq[SAnd]
so that another pattern matching several lines below will be exhaustive. In the dual code I’d need a var whose type is Seq[SOr]
and a corresponding pattern match several lines further on.
case class SOr(override val tds: SimpleTypeD*) extends SCombination {
// ... skipping lots of stuff
def conversion1(tds:Seq[SimpleTypeD]):SimpleTypeD = {
// TODO, this should be generalized to work for SAnd and SOr
// ABC + A!BC + X -> ABC + AC + X (later -> AC + X)
// AB !C + A !B C + A !B !C -> AB !C + A !B C + A !C
// AB !C + A !B C + A !B !C -> does not reduce to AB !C + A !B C + A
import adjuvant.Adjuvant.searchReplace
val ands = tds.collect{ case td@SAnd(_*) => td}
val orArgs = tds.map{
// A!BC -> AC
// ABC -> ABC
// X -> X
case td1@SAnd(andArgs@ _*) =>
// A!BC -> AC
// ABC -> ABC
val toRemove = andArgs.collectFirst{
case td@SNot(n) if ands.exists{
case SAnd(tds@_*) => tds == searchReplace(andArgs,td,Seq(n))
} => td
} // Some(!B) or None
toRemove match {
case None => td1
case Some(td) => SAnd.createAnd(andArgs.filterNot(_ == td))
}
case td => td // X -> X
}
SOr.createOr(orArgs)
}
// ...
}