Or you have a function which expects objects of type String as an input. But then you realize that in your case, null values can be handled just like empty strings. So the input type can be relaxed to String|Null.
Just "" != Nothing
If you want to handle empty strings as a input in haskell then you have a function of type `f :: String -> b` and you pattern match on your input?
f "" = someResult
f ...
Nothing assumes a proper null in that there is genuinely nothing to work with. Still you can make a function to handle it or use `maybe`?Haskell gets in the way by facilitating clashes of incompatible types: there are reasons to make breaking changes to type signatures that in more deliberately designed languages might remain unaltered or compatible, without breaking call sites.
You can achieve this by not changing the type and keeping the result as Maybe b. Dead code to handle `Nothing`, no harm done.
However, you clarify you don't want this because:
> Changing the type signature (which, by the way, could be at least in easy cases implicitly deduced by the compiler rather than edited by hand) allows new client code to assume that the result is present.
But this cuts both ways. If the old call site can assume there may be errors (even though the new type "b" doesn't specify them) then the new call site cannot assume there are no errors (what works for old must work for new).
I must say I see no real objection to the proposal at https://news.ycombinator.com/item?id=41519649 besides "I don't like it", which is not very compelling to me.
Why do you need to change the type signature at all? You "improved" [1] a function to make impossible for the error case to occur, but it's used everywhere and the calling code must handle the error case (I mean, that's what static typing of this sort). So there you have it: the client code is not rendered invalid, it just has dead code for handling a case that will never happen (or more usually, this just bubbles up to the error handler, not even requiring dead code at every call site).
As an aside, I don't see the problem with the "pile of monads" and it doesn't seem very complicated.
----
[1] which I assume means "I know I'll be calling this with values that make it impossible for the error to occur". If you are actually changing the code, well, it goes without saying that if the assumptions you made when choosing the type changed when re-writing the function, well... the calling sites breaking everywhere is a strength of static typing.