M
M
Markiv072021-11-26 23:19:42
Haskell
Markiv07, 2021-11-26 23:19:42

How does this code work in Haskell?

Hello, I just started learning Haskell. Here I found a code that every few characters (which we set as a parameter) inserts a given character (also a parameter).
But I can't understand how it works.

func1 :: [a] -> Int
func1 [] = 0
func1 (_:xs) = 1 + func1 xs

func2 :: Int -> [a] -> [a]
func2 _ [] = []
func2 n [email protected](_: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 '@')


I understand what func1 :: [a] -> Int does, for example, but what does this part of the code do
func2 n [email protected](_:xs')
   | n > 0     = func2 (n-1) xs'
   | otherwise = xs


Or this one
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


I can not. I understand that the task is very easy. But with knowledge of several popular programming languages, I absolutely can’t figure it out

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vasily Bannikov, 2021-11-27
@Markiv07

Generally figured out:


func3 means that when passing 0 as the second argument, you should always return the first argument unchanged.
And when passing an empty list as the first argument, it is always an empty list.
In other cases -
If func1 xs < n (func1 calculates the length of the list), then return xs, otherwise (some tricky thing)
In func2, using @, we simply pull out the first element of the list in _ (thanks to mikeyuriev for the correction), and the tail list - in xs'
And then there is a recursive call.
As a result, func2 will discard the first n elements of the list

func1 - recursively calculates the length of the list
func2 - discards the first n elements of the list
func3 - just alternates the elements of the list.
And now about the "complicated thing"
n `take` xs ++ [y] ++ func3 (drop n xs) n y
take takes the first n elements of the list (infix form is used here, that's why it's scary)
++ - concatenates two lists
drop - the same as func2
Thus, we take the first n elements of the list, glue the separator , and repeat the same with the remaining tail until the list ends.
For this reason, with an empty initial list, there is no point in interleaving, as well as with a zero interleaving period.
PS: the solution is nice and elegant, I like it.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question