Live data from Hacker News

Monads Explained Quickly

breck-mckye.com

41–42 of 42 posts

Re: Monads Explained Quickly

#41
post #33

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…

Lets take your first example, lets say someone creates some nifty useful function grabPiFromWebPage that returns a "JustValueOrError" (which has the result or an error message" instead of "Maybe".

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.

Re: Monads Explained Quickly

#42
post #33

Earlier quoted context omitted.

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…

Lets take your first example, lets say someone creates some nifty useful function grabPiFromWebPage that returns a "JustValueOrError" (which has the result or an error message" instead of "Maybe". 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 (aNonNullab…

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 
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.

Post reply on HN