@Markiv07

Как работает этот код на хаскеле?

Здравствуйте, начал изучать хаскель. Вот нашёл код который через каждые несколько символов (которые мы задаём параметром) вставляет заданый символ(также параметр).
Но не могу понять как он работает.
func1 :: [a] -> Int
func1 [] = 0
func1 (_:xs) = 1 + func1 xs

func2 :: Int -> [a] -> [a]
func2 _ [] = []
func2 n xs@(_:xs')
   | n > 0     = func2 (n-1) xs'
   | otherwise = xs

func3 :: [a] -> Int -> a -> [a]

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

main :: IO ()
main =  do
print(func3 "1234567" 2 '@')


Я понимаю что делает к примеру вот это func1 :: [a] -> Int но что делает вот эта часть кода
func2 n xs@(_:xs')
   | n > 0     = func2 (n-1) xs'
   | otherwise = xs


Или вот эта
func3 xs 0 y  = xs
func3 [] n y = []
func3 xs n y
 | func1 xs < n = xs
 | otherwise = n `take` xs ++ [y] ++ func3 (drop n xs) n y


Не могу. Понимаю что задание очень лёгкое. Но я со знанием нескольких популярных языков программирования, разобраться абсолютно не могу
  • Вопрос задан
  • 114 просмотров
Решения вопроса 2
vabka
@vabka
Токсичный шарпист
В общем разобрался:

func3 означает, что при передаче вторым аргументом 0 - надо всегда возвращать первый аргумент без изменений.
А при передаче первым аргументом пустого списка - всегда пустой список.
В остальных случаях -
Если func1 xs < n (func1 считает длину списка), то вернуть xs, иначе (какая-то сложная штука)

В func2 при помощи @ мы просто вытаскиваем первый элемент списка в _ (спасибо mikeyuriev за поправку), а хвоста списка - в xs'

А дальше идёт рекурсивный вызов.
В результате func2 отбросит n первых элементов списка

func1 - рекурскивно считает длину списка
func2 - отбрасывает первые n элементов списка
func3 - как раз чередует элементы списка.
А теперь про "сложную штуку"
n `take` xs ++ [y] ++ func3 (drop n xs) n y
take берёт первые n элементов списка (тут используется инфиксная форма, по тому и страшно)
++ - конкатенирует два списка
drop - то же самое, что и func2

Таким образом мы берём n первых элементов списка, приклеиваем разделитель, и повторяем то же самое с оставшимся хвостом, пока список не кончится.

По этой причине при пустом исходном списке нет и смысла чередовать, как и при нулевом периоде чередования.

PS: решение красивое и элегантное, мне нравится.
Ответ написан
@AlexSku
Программист по автоматике
А вот если пользоваться библиотеками, то, подключив два модуля, можно сделать коротко:
Prelude Data.List.Split Data.List> n = 2
Prelude Data.List.Split Data.List> intercalate "@" $ chunksOf n "1234567"
"12@34@56@7"
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы