You are mixing imperative and functional paradigms: let n = 0, let (x:xs) = (x:xs) ++ (x:xs)!!n, arg = arg - 1, n = n + 1 are (in your code) imperative expressions. You expect the values of n, (x:xs) and arg to be modified, but functional programming does not work like that.
The function you are declaring is meant to be pure: that means that you can't expect values to be modified (what we call a "side effect"). The only thing you can do is to call a new function (or the same function) with new arguments that are computed "on the fly" from the original arguments.
Let's try to be concrete.
You can't do:
arg = arg - 1
demo arg (x:xs)
But you can do:
demo (arg - 1) (x:xs)
The latter is a call of demo with arg - 1 as argument. The value of arg was never modified.
The main problem in your code is the n variable. It should be 0 at first call, and should be increased each time arg < length (x:xs) to add the next element from (x:xs) to the end of (x:xs) itself. Thus, the list will grow in a cyclic way until we can take the desired number of elements.
To reach that goal, you have to create an auxiliary function and to "move" the recursion into that auxiliary function:
demo :: Int -> [a] -> [a]
demo arg [] = []
demo arg (x:xs) = demo' arg 0 (x:xs) -- n = 0
where
demo' :: Int -> Int -> [a] -> [a]
demo' arg n l = if arg <= length l
then take arg l
else
-- call demo' with new parameters:
-- (x:xs) = (x:xs) ++ [(x:xs)!!n]
-- arg = arg - 1
-- n = n + 1
demo' (arg-1) (n+1) ((x:xs) ++ [(x:xs)!!n]) ```
Now, from the example you have given, arg is the constant number of elements in the list you want to create, so it should not be decreased. And you don't need the deconstruction of the list in (x:xs). Finally, with a little cleanup, you have :
demo :: Int -> [a] -> [a]
demo arg [] = []
demo arg l = demo' arg 0 l
where
demo' :: Int -> Int -> [a] -> [a]
demo' arg n l = if arg <= length l
then take arg l
else demo' arg (n+1) (l ++ [l!!n])
There is a far better way to achieve this (demo n=take n.cycle), but I tried to stay close to your original implementation.
possibly incorrect indentation. Thelet..inblock looks like it's incorrectly indented. Try to experiment with its indentation to get the code to compile. - Mark Seemannlet arg = arg-1andlet n=n+1are recursive definition which defineargandnas infinite looping computations. You don't want that. You are trying to mutate variables in Haskell, which was designed so to make that impossible. That approach is too imperative to work in a FP language. Roughly, the only way to "change" a variable is to call a function with the new value, eg.f 0 = 0 ; f n = f (n-1)defines a recursion that "decreases"nuntil it reaches 0. - chi