Я пытался решить этот вопрос в вики Haskell: https://wiki.haskell.org/99_questions/11_to_20 (проблема 12)
Мое решение таково:
data Repeats a = Single a | Multiple Int a deriving Show
encodelens :: Eq a => [a] -> [Repeats a]
encodelens xs = foldr (\x acc -> case acc of
[] -> [Single x]
(l:ls) -> case l of
(Single x') -> if x == x'
then [(Multiple 2 x)] ++ ls
else [(Single x)] ++ (l:ls)
(Multiple c x') -> if x == x'
then [(Multiple (c+1) x)] ++ ls
else [(Single x)] ++ (l:ls)
) [] xs
decodelens :: Eq a => [Repeats a] -> [a]
decodelens [] = []
deocdelens (r:rs) = case r of
(Single x) -> [x] ++ decodelens rs
(Multiple c x) -> take c (repeat x) ++ decodelens rs
decodelens
не работает, не работает:
decodelens [Multiple 4 'a',Multiple 2 'b',Multiple 2 'c',Multiple 2 'd',Single 'e',Multiple 3 'f']
"*** Exception: encode-len-with-cardinality.hs:(17,1)-(19,47): Non-exhaustive patterns in function decodelens
Я не уверен, как это не удается сопоставить с образцом.
Обновлять:
Как указано в комментариях ниже, ошибка в имени функции для второго совпадения с шаблоном deocdelens
. Интересно, есть ли способ избежать таких ошибок?
блин, такая простая ошибка. Как избежать подобных ошибок?
Мы все совершаем подобные ошибки, поэтому ghc - отличный партнер по парному программированию.
@Ngm Да, есть способ - включить предупреждения с помощью -Wall
! GHC должен предупредить вас о 1) неполном совпадении и 2) функции deocde
begin, определенной без аннотации типа deocde :: ...
. Второй должен указать на проблему.
Это действительно сложный тип ошибок. Обратите внимание, что если бы у вас была опечатка либо в подписи, либо в первом шаблоне для decodelens
, GHC пожаловался бы, потому что подпись должна быть «смежной» с определением функции.
Думаю, лучшее, что здесь можно сделать, - это включить -Wmissing-signatures
. Для приведенного выше кода это вызовет предупреждение о том, что функция верхнего уровня deocdelens
не имеет подписи. Конечно, это означает, что вам нужно явно писать сигнатуры для всех функций верхнего уровня, но в любом случае это обычно приветствуется.
Независимо от Haskell и других языков, одна вещь, которая действительно предотвращает этот вид проблемы, - это сделать привычкой имена никогда не печатать с более чем тремя буквами (кроме случаев, когда они пишутся в первый раз, обычно для подписи). Вот для чего есть автозаполнение.
Конечно, у этого есть свои проблемы - я не раз обнаруживал, что набираю неправильное имя первый раз, а затем автозаполняю - «вставляя» его в мою программу. Что тогда будет работать нормально, это просто немного неловко при чтении кода ...
Посмотрите на написание имени функции: deocde vs. decode.