0
votes

Bear with me as I am new to Haskell.

I'm trying to write a function that outputs:

The first list in the output should be the same as the input list. The second list in the output should contain every second element from the input list and so on.

example: func "ABCD" = ["ABCD","BD","C","D"]

I started by writing a function to get every nth element of a list:

everyN n xs = case drop (n-1) xs of
                [] -> []
                (z:zs) -> z : everyN n zs

Now I know that I just need to have a function which calls this function and increments the n value each time it is called, but I can't for the life of my think about how to write such a function or what would be the most concise way to express it. If possible I'd like to not use explicit recursion and use a haskell language function.

Can someone point me in the right direction?

1
Surely you can dream up a title which concisely summarizes your question.Matt Ball
The title is too generic to attract potential answerers. As a suggestion, try to generalize/adapt [everyN n "ABCDEFGHI" | n <- [1..9]]. Alternatively, use map instead of list comprehensions.chi
can you explain to me how i might use map in this scenario?leshow
i have never seen the syntax "| n <- [1..9]" before. is that line saying, call everyN for each value of n from 1 to 9?leshow
@leshow - yes exactly it says: make me a list ([ .. ]) where we generate the items of this list by everyN n xs and we take n from 1..9Random Dev

1 Answers

4
votes

I know it's kindof lame as @chi already gave you the comment - but maybe as a bonus I have an alternative for your everyN:

everyN :: Int -> [a] -> [a]
everyN n xs = every n xs
  where every _ [] = []
        every 1 (x:xs) = x : every n xs
        every m (_:xs) = every (m-1) xs

seqN :: [a] -> [[a]]
seqN xs = [ everyN n xs | n <- [1..length xs] ]

Here is the same using map (again as @chi mentioned):

seqN' :: [a] -> [[a]]
seqN' xs = map (flip everyN xs) [1..length xs]

explanation

Someone asked me to explain this a bit:

First look at map: map :: (a -> b) -> [a] -> [b] - now clearly we want to fit in everyN and as everyN has two arguments we surely want to partial apply it to something. The argument that is changing is not the input-list xs but the n - the xs will stay constant.

So surely we want to partial apply everyN to xs - but we cannot as this argument is in the wrong place.

flip to the rescue: this flips the arguments of everyN:

flip everyN :: [a] -> Int -> [a]

and we can partial apply this to xs and write:

flip everyN xs :: Int -> [a]

and finaly we can use this with map (of course ranging n over 1 .. length xs - because if we make jumps longer than length xs there will be nothing left to pick) as shown.

How do put this into one english sentence I don't know ;)