Неисчерпывающие паттерны в функции Exception в haskell

У меня есть этот код:

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 ""    

вход: foo "4a5b"

выход: "aaaabbbbb"

эта линия if (digitToInt(x)) == 0 проверяет, является ли число 0, если это так, то оно расширится с остальной частью строки:

Пример:

вход: foo "00004a5b"

выход: "aaaabbbbb"

и я добавил else if (digitToInt(x)) /= 0 проверить на другие случаи.

Однако это дает мне:

*Main> foo "4a5b"
"aaaabbbbb*** Exception: test.hs:(89,1)-(93,28): Non-exhaustive patterns in function foo

ошибка. Какие случаи я здесь пропустил?

1 ответ

Неисчерпывающие паттерны в функции foo

Эта ошибка возникает во время выполнения, потому что функция не была объявлена ​​в соответствии с шаблоном, приведенным в оценке. Этот частный случай не рассматривает конец хвоста списка.

Решение, которое я представляю ниже, является обобщением представленного варианта использования.

Обратите внимание на определение функции 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

Вот решение проблемы, представленной с учетом обобщения функции foo.

Код:

--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

Шаг за шагом:

  • Учитывая запись "003aA3b4vX10z"
  • Группировать по цифрам: ["003","a","A","3","b","4","v","X","10","z"]
  • Группировка по NoDigits: ["003","aA","3","b","4","vX","10","z"]
  • Воспроизвести и Concat: "aAaAaAbbbvXvXvXvXzzzzzzzzzz"

Тестовые случаи:

Prelude> foo "00004a5b"
Prelude> "aaaabbbbb"

Prelude> foo "4a"
Prelude> "aaaa"

Prelude> foo "4a10B"
Prelude> "aaaaBBBBBBBBBB"

Prelude> foo "3w1.1w6o1l4y1.1com"
Prelude> "www.woooooolyyyy.com"
Другие вопросы по тегам