Lets say I have:
newtype Animal = Animal Text
And I want to be able to pattern match on it like so:
f :: Animal -> (Bool, Text)
f = \case
NonHuman s -> (False, s)
Human -> (True, "human")
Basically, I want to interface with Animal as if it was defined like
data Animal = Human | NonHuman Text
Even though internally it's just a newtype of Text.
Note that I want the NonHuman pattern match to not match Animal "human".
I don't care too much about NonHuman and Human being valid in an expression context, indeed NonHuman should not be valid in an expression context (at least outside the module it's defined) as NonHuman "human" is bad.
I just want to abstract the implementation of this type from it's pattern matching syntax.
I guess you'd do something like this:
If you did care about making them valid in expression context, the following example shows the two other pattern synonym syntactic forms that would make this possible: