Live data from Hacker News

Why Maybe Is Better Than Null

nickknowlson.com

111–120 of 133 posts

Re: Why Maybe Is Better Than Null

#111
post #13

This article makes it seem like you'd have to explicitly check whether a Maybe value is Nothing when you use it. This is certainly safe , but it's also very awkward; as a contrived example, adding two numbers would look like this: case a of Nothing -> Nothing Just a -> case b of Nothing -> Nothing Just b -> a + b This is quite a bit of boilerplate hiding the expression that actually matters--a + b! Moreover, whenever…

You can also make Maybe an instance of various typeclasses for even nicer syntax: instance Num a => Num (Maybe a) where (+) = liftM2 (+) (-) = liftM2 (-) (*) = liftM2 (*) abs = liftM abs signum = liftM signum negate = liftM negate fromInteger = Just . fromInteger > Just 4 + 2 * Just 6 Just 16 > Nothing * 42 Nothing Notice how the fromInteger method allows you to freely mix Maybe and non-Maybe numbers.

Sounds like a bad idea to me. Even though Num doesn't have an explicit contract, we sort of expect it to behave "nicely".

But here we start with a nice ring like Integer and end up with a type that has this weird, extra element that has no inverse with respect to addition, etc.

Re: Why Maybe Is Better Than Null

#112

Earlier quoted context omitted.

Did you misunderstand? do x can result in Nothing if either a or b is Nothing, but (fromMaybe 0 a) + (fromMaybe 0 b) will always result in a number, with 0 being used in place of Nothing. If only one of them is Nothing, you'll get the value of the other, the Nothing having been treated as 0.

No, I didn't misunderstand. 'Nothing' and 0 are not interchangeable.

> No, I didn't misunderstand. 'Nothing' and 0 are not interchangeable.

Nobody said they were. That's idiomatic Haskell for something like this in Java when unboxing Integers:

  return (a != null ? a : 0) + (b != null ? b : 0);
As you can see, there is no adding Nothing to integers.

Re: Why Maybe Is Better Than Null

#113
post #82

Earlier quoted context omitted.

>That pattern just turns out to be very useful. Like NaN, it can be hard to track down where things went wrong.

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

Re: Why Maybe Is Better Than Null

#114

I've been working with engineers writing production Haskell for the first time; its lack of a "null" concept is proving to be absolutely incredible. In a high-uptime production environment, it's at least as valuable as Haskell's enshrinement of purity. We have a convention that all recoverable errors be captured in Either or Maybe. This policy is paying off in a huge way because the type system forces us to think abo…

Great to hear a real-world example of the concrete benefits, thanks!

Re: Why Maybe Is Better Than Null

#115
post #42

Earlier quoted context omitted.

Guava is definitely cool and I recommend it whenever I can. It's worth noting, however, that, as a Java library, it cannot provide the compile-time guarantees mentioned in the post. That is, your Option type could still be null and so you're still forced to perform run-time null checking. If you want the full benefit of Option types on the JVM, you might be better off with Scala.

The Optional in Guava just forces one to explicitly check for null and then get the container object during development. A typical pattern would be: Given an object a of type Optional , we write: if (a.isPresent()){ MyObject o = a.get() } Of course, I could still do a.get() without evaluating isPresent() and end up with an java.lang.IllegalStateException. Here, we are "reminded" to do the null check.

You can force Maybe in Haskell, and get a bad surprise at runtime as well.

Re: Why Maybe Is Better Than Null

#116
post #2

Guava for Java has Optional. Very nice, except for Java's horrid syntax for generics.

Guava is definitely cool and I recommend it whenever I can. It's worth noting, however, that, as a Java library, it cannot provide the compile-time guarantees mentioned in the post. That is, your Option type could still be null and so you're still forced to perform run-time null checking. If you want the full benefit of Option types on the JVM, you might be better off with Scala.

Not to mention that it does not make Java magically sprout pattern-matching abilities, which makes dealing with Maybes much more pleasant and natural.

Re: Why Maybe Is Better Than Null

#117

Great article! I'm especially glad to see "what have we gained?" in the FAQ, as it is probably the most frequently asked question I've heard. OP - I noticed you were thorough enough to mention both Fantom and Kotlin in one section, so for the preceding section you might want to note that CoffeeScript also has a safe-invoke operator like Groovy's.

Thanks! And I'll make a note for myself to put CoffeeScript in there too.

Re: Why Maybe Is Better Than Null

#118
post #64

If you work on types that might be null, you're bloody careful or you're in the wrong profession. We're not calling incompetent programmers a gazillion dollar mistake, even though they probably have caused as much.

Not everyone has the profession of herding spherical cows in vacuum ... in the real world lots of stuff can bait you in the ass.

this...makes me laugh, thanks ;-)

I would agree that the real world can bait one in the ass, out of the blue, just, what the, things are trying to eat my ass!

As for herding spherical cows and the vacuum, I'll do my best:

  val maybeCow = Some(1) // SomeOne is the speherical mu (i.e. you)
  maybeCow getOrElse 0 // Cow here becomes 1 with the universe
Were maybeCow initialized with a None value, then into the vacuum it goes...and out it comes with a safe 0 to keep order in our [application] universe.

Re: Why Maybe Is Better Than Null

#119
post #49

Earlier quoted context omitted.

True. I think it's also a covert argument for static type checking, though ;-).

Give me a statically typed Python and a type system that can handle external hardware poking around in its memory and I'm in ;) I'm sort of a fan of Haskell already, to tell you the truth.

I actually started designing statically typed Python, since it seemed a fun exercise. Halfway in I realised I was effectively redesigning Haskell with slightly different syntax and stopped.

Re: Why Maybe Is Better Than Null

#120
post #34

Earlier quoted context omitted.

I've worked with a code base in C++ where the code base would accumulate significant amounts of if (argumentX == null) return null; at the top of function signatures. It was just defensive programming. Maybe argumentX couldn't be null, but it would take time to figure that out (sometimes I did that, though). More code means harder to read and maintain, thus costing dollars. This would also be contagious: If a piece o…

I've worked on a lot of legacy Java code where these kind of null checks cause problems. The end up confusing things in corner cases. You should verify arguments at a top level, then let the code underneath blow up with a NullPointerException if something unexpected happened. Your stack trace will point at where the problem lies. I find for some reason that a lot of people want to use null instead of empty lists wher…

I agree with one exception: if you're storing the value passed down into a structure which will survive the call, then the value should be checked for null before being placed in the structure. This is because the eventual null pointer exception may occur long after it was put in the structure, obscuring how it got there.
Post reply on HN