I don't think this is possible in haskell. There are however, a few alternatives:
Factor out the common code with a where
binding
This doesn't make much sense in your example, but is useful if you have more code in the body of the case expression:
combine o1 o2 = case (o1,o2) of
(Valid, Invalid) -> handleInvalid
(Invalid, Valid) -> handleInvalid
...
where
handleInvalid = ...
Use wildcard patterns
In my experience, it doesn't happen so often that you want to use two or patterns in one pattern match. In this case, you can handle all the "good" cases and the use a wild card pattern for the rest:
combine o1 o2 = case (o1,o2) of
(Valid, Valid) -> Valid -- This is the only valid case
_ -> Invalid -- All other cases are invalid
This has the disadvantage that it bypasses the exhaustiveness checker and that you cannot use wildcard patterns for other purposes.
Use guards and ==
If the types you want to match against are enum-like types, you might consider making an Eq
instance. Then you can use ==
and ||
to match multiple constructors in one guard:
combine o1 o2
| o1 == Invalid && o2 == Valid || o1 == Valid && o2 == Invalid = Invalid
| ...
I agree that this doesn't look as nice and it also has the disadvantage of bypassing the exhaustiveness checker and doesn't warn you if patterns overlap, so I wouldn't recommend it.