views:

336

answers:

3
+11  Q: 

null instead of ==

I have just started to learn Haskell out of interest. I follow learnyouahaskell.com.

There I found this:

null checks if a list is empty. If it is, it returns True, otherwise it returns False. Use this function instead of xs == [] (if you have a list called xs)

Why is that? Why should we use null instead of == when both produce the same result?

Thanks.

+7  A: 

In my opinion, null myList reads more naturally than myList == [].

But the raison d'être for null is that it can be used as a function. For example, here's a function that takes a list of lists, and returns only the nonempty ones:

nonemptyLists :: [[a]] -> [[a]]
nonemptyLists = filter (not . null)

Without null, this would be more awkward:

nonEmptyLists = filter ([] /=)
Thomas
It seems every question I try answer this morning, someone answers it just before I hit post, with a better phrased answer :)
luke_randall
Thanks, and sorry :)
Thomas
However, `filter ([] /=)`.
KennyTM
How can inverse the operands and it ready even more naturally: `filter (/= [])`. Note that I'd always prefer pattern matching over an equality operator (unless in the above case of using it as a function)
Dario
See sdcvvc's answer: The real reason is that `null` works with any list, while `(== [])` only works with lists of `Eq`.
Piet Delport
@KennyTM: Of course, fixed. Thanks. @Piet Delport: That hadn't occurred to me. @sdcvvc: +1 :)
Thomas
+28  A: 

Comparing the lists with == requires elements to be comparable (denoted as Eq a).

Prelude> :t (==[])
(==[]) :: (Eq a) => [a] -> Bool

For example, [sin] == [] won't work, since you can't compare functions. It might seem stupid, but the type system must judge type of an expression without looking at its value.

An alternate check would be length xs == 0, this doesn't require equality but won't stop if your list is infinite (try length [1..] == 0). That's why there's a dedicated function.

null [] = True
null _ = False

Prelude> :t null
null :: [a] -> Bool     -- Notice lack of (Eq a).
sdcvvc
+4  A: 

Another benefit to using null is that many other containers (e.g. Data.Sequence, Data.ByteString, etc.) have a null function as well. This makes it easy to switch to another implementation simply by changing your import statements.

John