Rifti
Rifti

Reputation: 55

Yet another 'Non-exhaustive patterns in function'

Begginer Haskell Question. Actually I found very similiar question Haskell error: "non-exhaustive patterns"

Interactive shell:

Prelude> merge [] [] = []
Prelude> merge (x:xs) [] = x:xs
Prelude> merge [] (y:ys) = y:ys
Prelude> -- merge (x:xs) (y:ys)

Prelude> merge [][]
Exception
Prelude> merge [0][]
Exception: <interactive>:3:1-22: Non-exhaustive patterns in function merge

Prelude> merger [][0]
OK

In fact exceptions exist also in non-interactive mode

main = do
   print (merge [1,2,3] [])
   print (merge [] [1,2,3])
   print (merge [] [])


merge :: (Ord a) => [a] -> [a] -> [a]
merge (x:xs) [] = x:xs
merge [] (y:ys) = y:ys
merge [][] = []

However it depends on order of particulas special cases of merge where error appears. I dont't really know why this happens. Thanks in advance.

Upvotes: 2

Views: 816

Answers (1)

isekaijin
isekaijin

Reputation: 19742

There are two separate issues here.

You couldn't possibly have defined merge that way in GHCi. (Thanks for the correction, Alec!)

The first issue, which only happens in the interactive session, is that you are defining three separate functions called merge, each of which shadows the previous one. See here for someone who had a very similar problem to yours.

To enter a single multiline definition, you must use :{ and :}:

Prelude> :{
Prelude| merge [] [] = []
Prelude| merge (x:xs) [] = x:xs
Prelude| merge [] (y:ys) = y:ys
Prelude| -- merge (x:xs) (y:ys)
Prelude| :}
Prelude> 

However, in general, entering multiline definitions into GHCi is rather unpleasant, so you are better off storing your definitions into a normal .hs file and then loading this file into GHCi.


The second issue, which happens both in the interactive session and in the non-interactive program, is that your definition of merge isn't exhaustive: the case when both list arguments are nonempty isn't handled. Note that:

  • If either list argument is empty, merge must return the other list.
  • If both lists are nonempty, merge must extract the smallest head element (in either list), and then recursively merge the rest.

Thus, the correct definition of merge is:

Prelude> :{
Prelude| merge xs [] = xs
Prelude| merge [] ys = ys
Prelude| merge xxs@(x:xs) yys@(y:ys)
Prelude|   | x <= y    = x : merge xs yys
Prelude|   | otherwise = y : merge xxs ys
Prelude| :}
Prelude> merge [1,3..9] [2,4..10]
[1,2,3,4,5,6,7,8,9,10]
Prelude> 

Or, non-interactively:

merge xs [] = xs
merge [] ys = ys
merge xxs@(x:xs) yys@(y:ys)
  | x <= y    = x : merge xs yys
  | otherwise = y : merge xxs ys

Upvotes: 7

Related Questions