Hacker News new | ask | show | jobs
by notaddicted 4807 days ago
I don't have a whole lot of Haskell experience ... but these "Maybe" unwrapping functions are rare right? Like a null check I'd think that most of the time you make the check when you get the unreliable input or allocation or whatever, and thereafter in the guts of you program you have the certainty that the input has been "checked".
6 comments

The real trick is that, conceptually, these are not really "unwrapping" functions--instead, they're "propagating" functions. All they do is take Maybe values from deep inside your computation and string them through to the outside.

In practice, this means that you write a decent part of your program using these techniques, which creates a block of code that produces a Maybe value after taking a bunch of Maybe inputs. Then you only use a case statement at the very end, when you need to plug the Maybe value back into normal code.

All these functions are useful for one particular case: you don't know what to do with a Nothing value, so if you see one anywhere, you just pass it on: your final result is Nothing. That pattern just turns out to be very useful.

>That pattern just turns out to be very useful.

Like NaN, it can be hard to track down where things went wrong.

Except contrary to NaN, the type system encodes where it can exist and what its span is.
Right, you can rule out the pieces that are typed as "NaN-free" - hopefully that's a lot.

This is a great reason to avoid huge chunks of code stitched together staying inside Maybe, while still being convenient on the small scale.

But that's precisely why you abstract it; so you can switch to Error in need be...
> Like NaN, it can be hard to track down where things went wrong.

Unlike NaN, you have the freedom to not use it when you don't want it.

So, Either String a <=> Maybe a, but with a nice reason something went wrong.
Not quite. They are not restricted to error handling. You can have methods returning a Maybe something without it being an error (just like there are plenty of valid reasons for returning null instead of throwing an exception). You can also use Maybe in a data structure:

  data Employee = Employee { name : Text, spouse : Maybe Text }
You may also want to use Either to store two possible outcomes of an operation, though I would recommend using your own sum type for clarity:

  data MyOwnEither a b = MyLeft a | MyRight b
If Nothing is ever an error, than you can add code to handle that case. It isn't really different from some method returning an empty list and other functions being basically no-ops afterward.
Depends on the structure of your program. When the Maybe represents the return value of some function that might fail, like a "null" in another language, you'll probably try to eliminate the Nothing case fairly soon after getting it on, and if you have several to eliminate you might use the monad syntax to avoid repeated checks. (User input will commonly use an Either or Error rather than a Maybe, so that you have some error status for what went wrong, but the same principle applies.)

However, sometimes a Maybe represents an inherently "optional" part of your data model, such as "a Foo may have zero or one Bar". In that case, you'll probably hold onto the Maybe until the point where you'd actually read and use that field.

Yes, that's the great thing about Maybe — any code that doesn't need to care about the uncertainty is freed up from worrying about nulls by guaranteeing it won't get one. Most of your functions will usually deal with the unwrapped type, so if you try to pass the Maybe to these functions, the type-checker will say, "Wait, this function isn't expecting a Maybe. You've done something wrong here." So you have to do your "null check" at the point where you get your Maybe, and then you know for certain that the rest of your code won't explode with a NullPointerException or whatever.
They are pretty rare. Very few functions actually want to use nullable-arguments. Another reason why nullable by default is a bad idea.
Yes. This is perhaps the most important point in this thread. Monads and idioms are neat, but for Maybe's in most situations they are not really necessary since there is often a single point where you `case` on a Mabye and that's it.
Lots of things can give a maybe - lookup in a container, for instance - that might be lower down in your code.