stian
stian

Reputation: 1987

why the illegal non-exchastive pattern-matching in this code?

I wrote a pattern matching based code (commented out), which worked fine. I wanted to use "case of" in the hope of compacting my code a bit, but then it doesn't like how I have declared the empty list case (last one). I looked at some case of examples, and although not identical they seemed to support my declaration. Therefore I am not sure what I am doing wrong, and help is very much appreciated.

--1st way
mutate::[Char] ->Int
--mutate::[Char] ->[Int]
--mutate ('P':'E':'R':rest) = 0:mutate rest
--mutate ('P':'E':_:rest) = 1:mutate rest 
--mutate ('P':_:'R':rest) = 1:mutate rest
--mutate (_:'E':'R':rest) = 1:mutate rest
--mutate (_:_:'R':rest) = 2:mutate rest
--mutate (_:'E':_:rest) = 2:mutate rest
--mutate ('P':_:_:rest) = 2:mutate rest
--mutate (_:_:_:rest) = 3:[]
--mutate [] = [0]
--2nd way

mutate (f:s:t:rest) = case (f:s:t:rest) of
('P':'E':'R':rest) -> 0
('P':'E':_:rest) -> 1 
('P':_:'R':rest) -> 1
(_:'E':'R':rest) -> 1
(_:_:'R':rest) -> 2
(_:'E':_:rest) -> 2
('P':_:_:rest) -> 2
(_:_:_:rest) -> 3
([]) -> 0

main = print $ mutate []

Upvotes: 1

Views: 50

Answers (1)

Sibi
Sibi

Reputation: 48766

The problem is with this line:

mutate (f:s:t:rest) = case (f:s:t:rest) of

You are pattern matching in the first line itself. So this case will be only entered when the list has a minimum elements of 3. Something like this should work:

mutate :: [Char] -> Int
mutate xs = case xs of
               ('P':'E':'R':rest) -> 0
               ('P':'E':_:rest) -> 1 
               ('P':_:'R':rest) -> 1
               (_:'E':'R':rest) -> 1
               (_:_:'R':rest) -> 2
               (_:'E':_:rest) -> 2
               ('P':_:_:rest) -> 2
               (_:_:_:rest) -> 3
               ([]) -> 0

Upvotes: 5

Related Questions