Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell: Why is the pattern matching not exhaustive even if it compiles and executes?

Tags:

haskell

Learning Haskell, bit confused about the code hint here:

getMax :: [Int] -> Int
getMax [a] = a
getMax (a:b:as) = getMax ((if a >= b then a else b):as)
Pattern match(es) are non-exhaustive
In an equation for ‘getMax’: Patterns not matched: []

It works and finds the max of eg [5, 2, 6]. Does it need a pattern for the empty list? What's a reasonable return value then? Zero? Can I return something like undefined?

like image 365
TMOTTM Avatar asked Mar 03 '23 07:03

TMOTTM


1 Answers

Does it need a pattern for the empty list?

Not per se, since it is just a warning. As long as you never pass it an empty list, it will here work fine. But it is up to you to check that, and you can never be sure that somehow an empty list will be passed.

What's a reasonable return value then? Zero? Can I return something like undefined?

That is of course up to you to decide. You probably might want to make a distinction between the result of an empty list an a non-empty list. In Haskell usually therefore a Maybe is used. For example:

getMax :: [Int] -> Maybe Int
getMax [] = Nothing
getMax [a] = Just a
getMax (a:b:as) = getMax ((if a >= b then a else b):as)

or you can change the input, such that it is for example impossible to pass a non-empty list. We can here work with two parameters, so the signature is then getMax :: Int -> [Int] -> Int. Here the first parameter is the "head" of the list, and the second is the tail of the list:

getMax :: Int -> [Int] -> Int
getMax a [] = a
getMax a (b:as) = getMax (if a >= b then a else b) as

Using undefined is usually not a good idea. Yes than we no longer have a non-exhaustive pattern, but evaluating the undefined will raise an error. So it is only trading one problem for another one.

like image 61
Willem Van Onsem Avatar answered Apr 30 '23 10:04

Willem Van Onsem