Reputation: 55
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
Reputation: 19742
There are two separate issues here.
You couldn't possibly have defined (Thanks for the correction, Alec!)merge
that way in GHCi.
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:
merge
must return the other list.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