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)
}
// ...
}
```