I have this code:
import Data.Char
foo :: String -> String
foo (x:xs) = if (digitToInt(x)) == 0
then foo xs
else if (digitToInt(x)) /= 0
then replicate (digitToInt(x)) (head $ take 1 xs) ++ foo (tail xs )
else ""
input: foo "4a5b"
output: "aaaabbbbb"
this line if (digitToInt(x)) == 0
checks if the number is 0 if so then it will expand with the rest of the string:
Example:
input: foo "00004a5b"
output: "aaaabbbbb"
and I added else if (digitToInt(x)) /= 0
to check for the other cases.
However it gives me:
*Main> foo "4a5b"
"aaaabbbbb*** Exception: test.hs:(89,1)-(93,28): Non-exhaustive patterns in function foo
error. Which cases did I miss here?
Non-exhaustive patterns in function foo
This error occurs at runtime because the function has not been declared according to the pattern given in the evaluation. This particular case does not consider the end of the tail of a list.
The solution that I present below is an intention to generalize the use case presented.
Note the definition of the function reproduce
.
reproduce [] .. --Empty list
reproduce (x:[]) .. --A single value in the list
reproduce (x:y:[]) .. --A list with only two elements x and y
reproduce (x:y:xs) .. --A list with the first two elements x and y and the rest of the list xs
Here is a solution to the problem presented considering a generalization of the foo function.
The code:
--We import the functions to use
import Data.List (replicate, group, groupBy, all)
import Data.Char (isDigit)
--Grouping by digits
gbDigit :: String -> [String]
gbDigit = groupBy (\x y -> (isDigit x) && (isDigit y)) --ETA reduce form
--Grouping by nor digits
gbNoDigit :: String -> [String]
gbNoDigit s = fmap concat $ groupBy (\x y -> not (all isDigit x) && not (all isDigit y)) (gbDigit s)
--Prepare applying grouping
--by digit first and not by digit afterwards, therefore:
prepare = gbNoDigit
foo :: String -> String
foo x = concat $ reproduce (prepare x)
reproduce :: [String] -> [String]
reproduce [] = [] --Empty list, nothing to do
reproduce (x:[]) = [] --A numerical value and nothing to replicate, nothing to do
reproduce (x:y:[]) = (replicate (read x::Int)) y --A numeric value and a string to replicate, so we replicate
reproduce (x:y:xs) = (replicate (read x::Int)) y <> reproduce xs --A numeric value, a string to replicate, and a tail to continue
Step by step:
["003","a","A","3","b","4","v","X","10","z"]
["003","aA","3","b","4","vX","10","z"]
"aAaAaAbbbvXvXvXvXzzzzzzzzzz"
Test cases:
Prelude> foo "00004a5b"
Prelude> "aaaabbbbb"
Prelude> foo "4a"
Prelude> "aaaa"
Prelude> foo "4a10B"
Prelude> "aaaaBBBBBBBBBB"
Prelude> foo "3w1.1w6o1l4y1.1com"
Prelude> "www.woooooolyyyy.com"