3 ms·
You're right that in the case of grabPiFromWebPage returning a JustValueOrError, you'd have to apply a jvoeToMaybe function if you wanted to use Maybe's bind. I
by imh 11y ago
You're right that in the case of grabPiFromWebPage returning a JustValueOrError, you'd have to apply a jvoeToMaybe function if you wanted to use Maybe's bind. It could be an issue, but in practice, everyone uses the standard library tools for these things, so this issue shouldn't really come up. The general case problem can still arise, if you wanted to mix HTTP libraries, for example. It just isn't a huge issue in my experience. YMMV.
And I'd argue that the confusion of understanding the following isn't just a haskell issue:
do
x <- stuff
return (whatever x)
You just have to read the docs (or the code) and see what "stuff" and "whatever" do, regardless of whether you're in python, haskell, or whatever. In fact, one of my biggest pain points in python (my day job language) is that you can't as easily infer what "stuff" does, because you can't just look at type signatures. If I want to use randomUniform and see that it returns a Rand Double or something, I can just look up the Rand monad and see how they work. At least in a static language like haskell. Poorly documented monads would probably be a huge pain in a dynamically typed language. Even well documented ones would be tough to use in any interpreted language, because the compiler telling you "No, imh, that has to be a Rand Double, not a regular Double!" is lifesaving.
A pure language is a great match too, because practically all code is deterministic. If you write use it twice it WILL have the same result. The only exception is something in the IO monad. Of course, interacting with the real world/random numbers isn't deterministic, so (in haskell) you need to use monads to do anything. Hence the proliferation of tutorials. So if you see a function that has type (IO Double), it's a nondeterministic double. But if it doesn't have that, then you know it's deterministic, just by looking at the type signature. This is the hardest part of learning haskell.
The point about all this not being self evident because of complicated structures is well made though. There's serious cognitive overhead sometimes, but it's a tradeoff. I've quipped a few times that haskell code doesn't get more complex, it just gets harder. It's a joke, but there's an element of truth to it. You can avoid some explosions in how many edge cases there are to consider by going up a level of abstraction. For example, using functions that operate on lists, you never have to worry about index out of bound exceptions, or using Maybe you don't have to think about handling nulls. But you do have to grok the map function for List or Maybe. Sometimes it's worth it, other times it's not.