Haskell странное (для меня) поведение - PullRequest
0 голосов
/ 17 декабря 2018

Я работаю над 99 проблемами Haskell (https://wiki.haskell.org/99_questions/1_to_10), у меня есть вопрос, касающийся проблемы № 8.

8 Problem 8
(**) Eliminate consecutive duplicates of list elements.

If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed.

Я успешно решил эту проблему с помощью функции foldr.

compress :: Eq e => [e] -> [e]
compress =  let f v [] = [v]
                f v acc 
                        | head acc == v = acc
                        | otherwise = v:acc
            in foldr f []

Но когда я пытаюсь решить ту же проблему с рекурсией, как это:

compress' :: Eq e => [e] -> [e]
compress' = let f acc [] = acc
                f [] (x:xs) = f [x] xs
                f acc (x:xs) | x == last acc = acc ++ f acc xs
                             | otherwise = f (acc ++ [x]) xs 
            in f []

Я вижу действительно странное поведение. Я вижу такой результат этой функции:

compress' "aaaabccaadeeee"
"aaaabcabcaabcadeabcadeabcadeabcade"

Но если я добавлю точку останова в строке

compress' = let f acc [] = acc

, это даст мне правильный результат:

ghci> compress' "aaaabccaadeeee"
"aaaabcabcaabcadeabcadeabcadeabcade"
ghci> :break 304
Breakpoint 7 activated at haskell-tut.hs:304:28-30
ghci> compress' "aaaabccaadeeee"
"aaaabcabcaabcadeabcadeabcadeStopped in Main.compress'.f, haskell-tut.hs:304:28-30
_result :: [Char] = _
acc :: [Char] = "abcade"
[haskell-tut.hs:304:28-30] ghci> :con
abcade"
ghci>

Мне кажется, что это что-то из лени Хаскелла ....Это мое лучшее предположение. Может ли кто-нибудь объяснить, почему я получаю этот странный результат во время выполнения и правильный результат во время выполнения с точкой останова?

1 Ответ

0 голосов
/ 17 декабря 2018

Проблема возникает из выражения ниже:

x == last acc = acc ++ f acc xs

Не нужно добавлять строку acc в начале результата, поэтому исправление должно быть:

x == last acc = f acc xs

Обратите внимание, что acc содержит нужный вам нужный результат, то есть строку без последовательных дубликатов, поэтому вы можете увидеть правильный результат acc :: [Char] = "abcade" в точке останова, когда входной список равен [].Но когда он возвращается, он объединяет предыдущий результат как acc ++ "abcade", из которого "abcade" в конце "aaaabcabcaabcadeabcadeabcadeabcade"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...