Простая задача на Haskell, но не знаю, как работает этот код

#haskell

Вопрос:

Я начал изучать Хаскелла. Я нашел код, который каждые несколько символов (которые мы задаем с помощью параметра) вставляет заданный символ (также параметр). Но я не могу понять, как это работает.

 func1 :: [a] -gt; Int func1 [] = 0 func1 (_:xs) = 1   func1 xs  func2 :: Int -gt; [a] -gt; [a] func2 _ [] = [] func2 n xs@(_:xs')  | n gt; 0 = func2 (n-1) xs'  | otherwise = xs  func3 :: [a] -gt; Int -gt; a -gt; [a]  func3 xs 0 y = xs func3 [] n y = [] func3 xs n y  | func1 xs lt; n = xs  | otherwise = n `take` xs    [y]    func3 (drop n xs) n y  main :: IO () main = do print(func3 "1234567" 2 '@')  

Я понимаю, что, например, делает эта функция 1 :: [a] -gt; Intgt;, но что делает эта часть кода, я не понимаю?

 func2 n xs@(_:xs')  | n gt; 0 = func2 (n-1) xs'  | otherwise = xs  

Или вот этот?

 func3 xs 0 y = xs  func3 [] n y = []  func3 xs n y  | func1 xs lt; n = xs  | otherwise = n `take` xs    [y]    func3 (drop n xs) n y  

Не могли бы вы мне это объяснить? Спасибо

Ответ №1:

Я постараюсь пройти через функции одну за другой.

func1 xs вычисляет длину xs . [] имеет длину 0 , и длина x : xs на единицу больше длины xs .

func2 n xs@(_:xs') не вызывается никакой другой функцией, но я попытаюсь объяснить, что бы она делала, если бы была вызвана. Схема xs@(_:xs') может показаться необычной, поэтому давайте разберем ее. xs@pat привязывает переменную xs к шаблону pat . В данном случае закономерность такова _:xs . Подчеркивание соответствует любому значению и отбрасывает его. xs' соответствует любому списку. Если бы вы позвонили func2 3 [1, 2] , то этот шаблон был бы согласован. Внутри области действия функции xs будет равно [1, 2] и xs' будет равно [2] . Если n gt; 0 , то func2 называет себя, где xs был заменен хвост xs , и n был заменен n - 1 . Это продолжается до n = 0 тех пор xs , пока не будет просто сохранено. Следовательно, func2 n xs делает по существу то же самое, drop n xs что и . По крайней мере, до тех пор, пока length xs gt;= n .

Как вы сказали, func3 вставки y в каждой n позиции xs . Есть несколько случаев: n = 0 является крайним случаем без очевидного поведения, поэтому func3 ничего не делает. Если xs = [] нет никакой n позиции в xs so func3 , снова ничего не делает. Последний шаблон различает два случая использования охранников. Это необходимо, потому что нет шаблонов для «списка по крайней мере длины n «, если n только во время компиляции не известна какая-либо константа. В первом случае длина xs (рассчитанная с использованием func1 ) меньше n . Опять же, вставлять нечего, так как позиции нет n . Вторая стража-это место, где происходит волшебство. otherwise это буквально справедливо True , и поэтому это «всеобщий» охранник. Результат может быть описан следующей процедурой: Сначала мы берем первые n элементы xs . Затем мы добавляем ( ) список из одного элемента [y] . Затем мы добавляем результат func2 применения к оставшемуся списку.

Это первый раз, когда я опубликовал ответ на SO, так что не стесняйтесь спрашивать, было ли что-то неясно!

Комментарии:

1. Спасибо за объяснение