Как работает этот код на хаскеле?
В общем разобрался:

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