Or patterns
I’d like to suggest introducing or patterns. I’ll explain the simplest case of this and try to give some justification for inclusion in the language, then work up to more complicated examples. The simplest case is to simply allow multiple cases before the -> in a case expression. Something like this:
isEmpty : Maybe String -> Bool
isEmpty mString =
    case mString of
        Nothing
        Just "" ->
            True
        Just _ ->
            False
Ocaml is an example language that includes this functionality.
Motivation
Allowing the use of these patterns has the following advantages:
- It’s a bit easier to see that two (or more) cases produce the same answer.
 - Some code duplication removal. If multiple cases have the same answer, then currently you have to copy that answer. If the answer is a complicated expression you can use a 
let(or just another definition within an existinglet), however doing so produces names at a scope larger than you would really want, and may involve unnecessary computation (I don’t know if the compiler is smart enough to move such expressions around). In particular the name that is introduced must be available in all cases, even though you are only using it in a subset of them. - Speculative: I would hope it would reduce the instances of 
_ ->because it’s easier to list the remaining cases, thus meaning that updates to a custom type are more likely to produce a compiler error where appropriate. - More speculative: It’s possible that allowing this can improve the compilation of pattern matching. See for example: http://pauillac.inria.fr/~maranget/papers/opat/
 
The two patterns in the or pattern above do not introduce any new variables. But they could, and when that happens of course both patterns must introduce the same names at the same types.
In theory or patterns could be restricted to the top level but they could also be sub-patterns, Such as:
containsEmptyName : Tree -> Bool
containsEmptyName tree =
    case tree of
        Node (Nothing | Just "") _ _ ->
            True
        Node (Just _) left right ->
            case containsEmptyName left of
                True ->
                    True
                False ->
                    containsEmptyName right
        Leaf _ ->
            False
Here the or pattern is nested within a constructor pattern. I’ve had to invent syntax for it and used | to separate the two patterns. I’m not suggesting that this is indeed the appropriate syntax.
Small example, consider testing an Http.Error for whether or not it is probably network related:
type Error
    = BadUrl String
    | Timeout
    | NetworkError
    | BadStatus Int
    | BadBody String
Currently you have to write this as:
isNetworkRelated : Error -> Bool
isNetworkRelated error =
    case error of
        Timeout ->
            True
        NetworkError ->
            True
        BadUrl _ ->
            False
        BadStatus _ ->
            False
        BadBody _ ->
            False
The lazy might do this following, meaning you won’t get warned if a new constructor is added to the Error type:
isNetworkRelated : Error -> Bool
isNetworkRelated error =
    case error of
        Timeout ->
            True
        NetworkError ->
            True
        _ ->
            False
Under the proposal to add or-patterns you can do this:
isNetworkRelated : Error -> Bool
isNetworkRelated error =
    case error of
        Timeout
        NetworkError ->
            True
        BadUrl _
        BadStatus _
        BadBody _ ->
            False
It’s arguable, but to my mind the latter is clearer than the lazy version even if we forget about being warned when a constructor is added to the Error type.
Disadvantages
- It increases the complexity of the language, I would say fairly modestly.
 - This would likely lead to developers asking for ‘guards’ on cases a la Haskell, or ‘not’ patterns.
 - It might be easier to mistakenly include a pattern in a group? Well it almost certainly would be easier, I’m not sure whether it represents a major problem.
 - Speculative: Might produce error messages that are difficult to understand.
 
Not a disadvantage but a counter-argument to advantage number 2: This doesn’t solve all instances of this problem because sometimes multiple cases share an intermediate value but not the entire answer.
Other considerations
A potential corner case is related with Elm’s special type-variables
type Number = MyInt Int | MyFloat Float
...
    case n of
        MyInt x
        MyFloat x ->
            x + 1
I think in this case the compiler should reject the or-pattern as defining the same variable with different types, the fact that the expression is valid for both is neither here-nor-there as you could, for example get the same thing by using identity or always when the two different types don’t even share a class. Note that in any case the result of the expression is a different type anyway, though it’s isn’t hard to come up with an expression that would have exhibit this problem but produce the same type.
Extensible record types may also represent something of a corner-case. Consider the same example but instead of Int and Float you have some record type and some extension of the same record type.
Relevant link
- Ghc proposal to add Or-patterns to Haskell: https://github.com/ghc-proposals/ghc-proposals/pull/43