Why am I getting a parse error on input `|'

Viewed 122
takeEveryNth :: [Int] -> Int -> [Int]
takeEveryNth g destination
   | [] destination == []
   | otherwise = [g !! destination] ++ takeEveryNth (drop (destination+1) g) destination

I keep getting the error message in the title for line 4 of this code ( | otherwise =…) I have tried changing the indentation but can't figure why I am getting this error

2 Answers

The reason it doesn't work is because your first guard expression does not evaluate to a boolean expression where = follows.

I think this should do it:

takeEveryNth :: [Int] -> Int -> [Int]
takeEveryNth g destination
   | length g <= destination = []
   | otherwise = [g !! destination] ++ takeEveryNth (drop (destination+1) g) destination

Demo

Test:

takeEveryNth [1..10] 2

Produces:

[3,6,9]

and

takeEveryNth [1..10] 1

Produces:

[2,4,6,8,10]

The reason that this does not work is because the parser expects a singe =, not a == for a guard. That being said, you use guards as if they are patterns. Guards work with expressions that have type Bool. So a guard like | [] destination = ... makes no sense.

You likely want to implement something like:

takeEveryNth :: [Int] -> Int -> [Int]
takeEveryNth [] _ = []
takeEveryNth g destination = [g !! destination] ++ takeEveryNth (drop (destination+1) g) destination

This however is still not sufficient, since if the list g contains less than n elements, the g !! destination will error. Furthermore wrapping the values in a singleton list is not necessary, you can use the "cons" function (:) :: a -> [a] -> [a]. You can make use of drop :: Int -> [a] -> [a] to safely split at a given element, and then perform pattern matching, for example in a pattern guard on that result:

takeEveryNth :: [Int] -> Int -> [Int]
takeEveryNth g n
    | (x:xs) <- drop (n-1) g = x : takeEveryNth xs n
    | otherwise = []
Related