Live data from Hacker News

Why Maybe Is Better Than Null

nickknowlson.com

51–60 of 133 posts

Re: Why Maybe Is Better Than Null

#51

Earlier quoted context omitted.

Another way to go would be to use some functions that conceal the mechanics of Maybe. For instance: (fromMaybe 0 a) + (fromMaybe 0 b) This will always produce a number and it's pretty clear why you'd get the one you'd get.

I don't agree that it's pretty clear. 0 is a perfectly valid outcome of an addition, and you can't count on being the last calculation in the chain.

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.

Re: Why Maybe Is Better Than Null

#52

Earlier quoted context omitted.

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.

At least in Clojure, it's considered bad form to extend your own protocols (aka instance type classes) to types you don't own. Isn't that also true of Haskell? Haskell's type classes, unlike ML functors (I think), are "coherent", which means that you can't have scoped or multiple instances for the same type, lest you risk breaking the type system. With that in mind, extending Maybe to Num would mean a reduction the n…

Defining instances for both someone else's class and someone else's type is considered bad and GHC will warn:

http://stackoverflow.com/questions/3079537/orphaned-instance...

There are occasions where it can be useful to have a module export an orphan instance for compatibility before it makes it into the more appropriate spot in the standard libs.

And you're right you can't have multiple instances for the same type; a newtype wrapper is required.

Re: Why Maybe Is Better Than Null

#53
post #31

Earlier quoted context omitted.

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

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

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.

Re: Why Maybe Is Better Than Null

#54

Earlier quoted context omitted.

I don't agree that it's pretty clear. 0 is a perfectly valid outcome of an addition, and you can't count on being the last calculation in the chain.

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.

Re: Why Maybe Is Better Than Null

#56

In object-oriented modelling you often see the Null Object pattern being used to the same effect. http://en.wikipedia.org/wiki/Null_Object_pattern It needs static analysis tools such as Code Contracts (C#) or SpringContracts (Java) to make it really robust.

The null object pattern and Maybe/Option are different concepts. The most important point: A NOP for some type T exposes T's API directly, while Maybe/Option has its own API (and the type system enforces that Option[T] can't be treated as a T).

Re: Why Maybe Is Better Than Null

#58
post #55

[deleted]

Java is really not the greatest example here. In fact, the source article here is basically saying as much by calling into question some of the Java conventions.

I think you'll find in a language like Haskell that a lot more information can be embedded in types than in something like Java.

Re: Why Maybe Is Better Than Null

#59

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.

You did misunderstand: you took a friendly illustration of an alternative way to use Maybe as some kind of absolutist degree. Well, put down your sword. Much of the time when you have Maybe you also have a sensible default value and you want to use that rather than live the rest of your life inside Maybe. fromMaybe is just a handy way to deal with that case.

Re: Why Maybe Is Better Than Null

#60

Earlier quoted context omitted.

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.

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

Lots of things can give a maybe - lookup in a container, for instance - that might be lower down in your code.
Post reply on HN