#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. Спасибо за объяснение