0

When i input: decoder "a12b13"

I get the error: "a12b1*** Exception: Lib.hs:(131,5)-(134,302): Non-exhaustive patterns in function complex_decode

I can't see why i'm getting a pattern match issue as the code should always recurse untill i get an empty list and only one argument is passed to it. I think there must be an issue with my base case but i'm not sure what it is. any help would be greatly appriciated. Here is where i think the problem in my code is:

    decoder :: [Char] -> [Char]
    decoder [] = []
    decoder (x:y:xs) 
        | ((x /= '1'|| x /= '2'|| x /= '3'|| x /= '4'|| x /='5'|| x /= '6'|| x /= '7'|| x /= '8'|| x /= '9'|| x /= '0') && (y /= '1'|| y /= '2'|| y /= '3'|| y /= '4'|| y /='5'|| y /= '6'|| y /= '7'|| y /= '8'|| y /= '9'|| y /= '0')) = x : decoder (y:xs)
        | otherwise                                                                                                                                                                                                                      = repeat_char x (string_to_int(getInt False (y:xs))) ++ decoder xs
sjakobi
  • 3,546
  • 1
  • 25
  • 43
  • 1
    `decode [x]` is not covered. Since you recurse on the tail, eventually, you will obtain a list with one element – Willem Van Onsem Nov 17 '20 at 12:13
  • You might want to look at using a parser library instead. There's a bit of a learning curve, but it's relatively simple to create a parser will give you a list of type `[(Int, Char)]`, which can then be converted to your desired string with `concatMap (uncurry replicate)`. – chepner Nov 17 '20 at 13:04
  • As the `Char` type is an instance of `Ord`, you could have a test like: `((x < '0') || (x >'9'))` that would be more readable. I guess it would not count as a library function. And you might well have another time-honored house rule than bans source code lines longer than 80 or 100 characters. – jpmarinier Nov 17 '20 at 13:30
  • tag:[tag:non-exhaustive-patterns] – Will Ness Nov 17 '20 at 15:39

1 Answers1

0

(x:y:xs) requires that you have an array with at least two elements, and [] only covers when you have zero elements. You should also cover when you have one element, [x]. Also, your condition is wrong. (x /= '1' || x /= '2') will always be true, since it can't be equal to both at the same time. I think you meant to use && instead of ||. Regardless, there's a cleaner solution involving notElem:

digits :: [Char]
digits = "0123456789" -- or ['0'..'9'] since they're adjacent in the ascii space

decoder :: [Char] -> [Char]
decoder [] = []
decoder [x] = -- cover this case
decoder (x:y:xs)
    | x `notElem` digits && y `notElem` digits = x:decoder (y:ys)
    | otherwise = repeat_char -- ...

I also question if you need to have checks for both x and y being digits, but without seeing the rest of your code I can't tell. Also, consider using isDigit in Data.Char, which does the digit check for you without having to manually define digits, or replicate which allows you to repeat an element a certain number of times, or read, which lets you read a string to an int. notElem is pretty easy to make yourself:

notElem' :: (Eq a) => a -> [a]
notElem' _ [] = True
notElem' v (x:xs)
    | v == x = False
    | otherwise = notElem' v xs
Aplet123
  • 33,825
  • 1
  • 29
  • 55
  • Thankyou for this answer! you're right about the OR to AND and notElem, but i'm not allowed to use any built in functions(such as notElem). I'm doing character decoding so I need to check if x is a letter and y is a letter as then x is a character of length 1. – User200202929 Nov 17 '20 at 12:51
  • @User200202929 I've edited my answer to include a self-made `notElem`. – Aplet123 Nov 17 '20 at 12:56
  • @User200202929 https://stackoverflow.com/help/someone-answers – Will Ness Nov 17 '20 at 15:42