Deprecation in the type
signature

The fact that a function is deprecated should not just show up in the
function name (_DEPRECATED suffix), or in the compilation logs
as a warning. If that is all we add to discourage the use of deprecated
functions, the barrier to using them may still be too low. We should actively
make it un-fun to use deprecated functions.

The trick will be to have deprecation show up in type signatures. Let’s
get started with this annoying newtype wrapper around a function:

newtypeDeprecated a b =Deprecate { useDeprecated :: a -> b }

Now, to deprecate a function, we just change a function
myFunction into myFunction_DEPRECATED by putting it
in a where clause and adding the _DEPRECATED suffix. (Don’t
forget to add a deprecation plan in the comments!)

The smiling poop operators

Before we delve into how to fix up the rest of the code so that it
compiles again, let us make using deprecated code even nastier. We can make a
new operator to un-deprecate a Deprecated function:

(💩) ::Deprecated a b -> (a -> b)
(💩) = useDeprecated

Now we can hide the useDeprecated function and the
Deprecate constructor so that this operator has to be used. We
can then still use myFunction_DEPRECATED if it is absolutely
necessary, but it is already not very fun anymore:

λ> myFunction_DEPRECATED 💩 AB

Sadly, deprecating functions with multiple parameters will now require a
lot more parentheses. That could be smellier! Here is the double poop
operator: