Earlier quoted context omitted.
For the "maybe a" case, you then need to take all of your code and place it in some machinery that knows what "maybe" means, and how to extract "a" from it. And then you need to write or convert all your functions to return maybe values rather than just plain values. All of this could be easily done with exceptions. Why do all that when something simple like an exception will do, is easily understood, and easily code…
Yeah sure, I'm in the mood to write, but didn't want to cram too much into one post, else risk muddying the message. It turns out that doing (a -> m b) instead of (m a -> m b) can still allow really cool control flow. But first let me address some of your points. >For the "maybe a" case, you then need to take all of your code and place it in some machinery that knows what "maybe" means, and how to extract "a" from it…
If I understand it correctly (please bare with me if I make a mistake, I'm not very familiar with haskell)
Just 1 >>= \one ->
Just 2 >>= \two ->
aNullableFunction one >>= \x ->
grabPiFromWebPage >>= \w ->
return (aNonNullableFunction two) >>= \y ->
return (one * y + two * x + w)
wouldn't work, because grabPiFromWebPage returns the wrong type of monad. If you wanted to see the error on failure, you'd have to have some special bind for aNullableFunction to convert its monad to "JustValueOrError", as well as convert the "pure" functions.So now, because you want to add a new kind of function to the implementation chain, you have to write some sort of converter function for both the "maybe" and the "pure" functions. It seems brittle.
Secondly, it is also confusing as to what is actually happening in the code. When I look at:
do
x
I then have to go some place (where I don't know because I don't know Haskell), and figure out what is happening there to confirm that this is operating properly. And if I make a mistake doing that, I could easily get the wrong impression and possibly think, for example in this case, that code isn't deterministic.Finally, I've also seen examples where probability distributions are calculated and complex things like that. I could easily see a combinatoric slow down that is not self evident because everything is hidden in these complicated structures.