Реализация функции обертывания на Haskell - PullRequest
0 голосов
/ 25 ноября 2018

У меня проблема с реализацией этой функции:

ТИП ПОДПИСЬ

wrap :: Int -> a -> [a] -> [a]

НАЗНАЧЕНИЕ

Вставка x в каждую n -ую позицию всписок xs.

ПРИМЕРЫ

wrap 1 '+' "a" : "+a+"

wrap 2 '+' "a" : "+a"

wrap 2 '+' "abcd" : "+ab+cd+"

ОПРЕДЕЛЕНИЕ

wrap _ _ [] = []
wrap n x xs = insertAfter 0 xs
        where insertAfter = undefined

Как можно реализовать это, я просто не могу понять это.РЕДАКТИРОВАТЬ:

Полный вопрос: Реализовать функцию wrap, которая генерирует список, который начинается со второго аргумента wrap (x), за которым следует столько записей из третьего аргумента wrap (xs), сколько продиктовано первым аргументом wrap (n).Повторяйте, пока третий аргумент не будет пустым.В результирующем списке каждый n-й элемент должен быть равен x.Вставьте x в конце, если длина xs равномерно делится на n.Подсказка: реализуйте функцию wrap в терминах функции insertAfter, которая принимает число m и список элементов xs, которые уменьшают m при удалении элементов из xs и вставляют x всякий раз, когда m достигает 0.

Я почти получилit:

 wrap _ _ [] = []
 wrap n x xs = insertAfter 0 xs
   where insertAfter 0 xs = x : insertAfter n xs
         insertAfter _ [] = undefined
         insertAfter n xs = take n xs ++ (wrap n x (drop n xs))

, но на примере: wrap 2 '+' "abcd": wrap 2 '+' "abcd": "+ ab + cd +" Я получаю "+ ab + cd", поэтому«+» отсутствует.

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

Вы можете сделать следующее

wrap :: Int -> a -> [a] -> [a]
wrap _ _ [] = []
wrap n c cs | n == length cs = c:cs++[c]
            | otherwise      = c:x ++ wrap n c y
              where (x,y) = splitAt n cs

n == length cs условие требуется, потому что оба значения splitAt 2..n "a" и splitAt 1 "a" дают ("a","").Также я предполагаю n >= 1 всегда.

0 голосов
/ 25 ноября 2018

Я позволил себе изменить аргумент, который вы передаете, на insertAfter.Очень часто немного удобнее считать вниз , чем считать вверх , и это также верно и здесь.

wrap :: Int -> a -> [a] -> [a]
wrap _ _ [] = []
wrap n delim = insertAfter n
  where
     -- We've reached zero. So we insert the delimiter and
     -- reset the counter to n.
     insertAfter 0 xs = delim : insertAfter n xs
     -- All done
     insertAfter _ [] = ???
     -- Still some work to do
     insertAfter k (y : ys) = ???

В сторону: то, что вы назвали«контракт» - это то, что мы называем подписью типа .Фактический контракт обычно дает гораздо больше подробностей о том, что ожидается от аргументов и что гарантировано от результата.Например, в контракте здесь указывается, что первый аргумент wrap должен быть положительным, и дается объяснение того, что делает функция.

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