I have to learn Haskell for university and therefor I\'m using learnyouahaskell.com for the beginning.
I always used imperative languages so I decided to practice Haskell
Because _
literally means anything apart from explicitly specified patterns. When you specify (_:_)
it means anything which can be represented as a list containing at least 1 element, without bothering with what or even how many elements the list actually contains. Since the case with an explicit pattern for empty list is already present, (_:_)
might as well be replaced by _
.
However, representing it as (_:_)
gives you the flexibility to not even explicitly pass the empty list pattern. In fact, this will work:
-- | Test whether a list is empty.
null :: [a] -> Bool
null (_:_) = False
null _ = True
Demo
You can't just turn the clauses around with your solution:
mNull' :: [a] -> Bool
mNull' _ = False
mNull' [] = True
this
will always yield False
, even if you pass an empty list. Because the runtime doesn't ever consider the []
clause, it immediately sees _
matches anything. (GHC will warn you about such an overlapping pattern.)
On the other hand,
null' :: [a] -> Bool
null' (_:_) = False
null' [] = True
still works correctly, because (_:_)
fails to match the particular case of an empty list.
That in itself doesn't really give the two explicit clauses an advantage. However, in more complicated code, writing out all the mutually excluse options has one benefit: if you've forgotten one option, the compiler can also warn you about that! Whereas a _
can and will just handle any case not dealt with by the previous clauses, even if that's not actually correct.
I'll add on to what leftaroundabout said. This is not really a potential concern for the list type, but in general, data types sometimes get modified. If you have an ill-conceived
data FavoriteFood = Pizza
| SesameSpinachPancake
| ChanaMasala
and later you learn to like DrunkenNoodles
and add it to the list, all your functions that pattern match on the type will need to be expanded. If you've used any _
patterns, you will need to find them manually; the compiler can't help you. If you've matched each thing explicitly, you can turn on -fwarn-incomplete-patterns
and GHC will tell you about every spot you've missed.