For example, you can encode Just as fJust :: a -> (a -> b) -> b and Nothing as fNothing :: b -> b. fJust receives a computation that accepts argument of Just constructor, while fNothing receives just a value to be returned. Or, alternatively, you can look at the type of maybe function which is pattern matching on Maybe in disguise: maybe :: b -> (a -> b) -> Maybe a -> b.
(I believe this method is called Church encoding)
But when you go from structure of types and patterns to functions, you lose the ability of analysis (of exhaustivity or anything else). You now deal with something that is Turing complete instead of fixed size structure.
And this is delimition of "possible" and "impossible". With the Church encoding analysis of matching completeness is impossible and even writing matchers for lists or trees is nigh to impossible, actually.