Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get element's index in list when using foldl

Tags:

haskell

I have to code a function to calculate (sum k=1 to n) (-1)^(k+1) * a_k from list [a_1,a_2,a_3,..a_n] using foldl.

calculate list = foldl (\x xs -> 
    x + (xs * (-1)^(??? + 1))
    ) 0 list

I managed to write this code, but I don't have a clue what should replace ???, how to get index of an element in given list.

like image 236
J.G. Avatar asked Dec 18 '22 17:12

J.G.


2 Answers

Thanks to comment by Willem, I managed to do this in this way:

calculate list = foldl (\x (index,el) -> 
    x + (el * (-1)^(1 + index))
    ) 0 (zip [1..length(list)] list)

For me, it's more readable one, because I'm newbie, I just posted it for others :)

like image 77
J.G. Avatar answered Dec 20 '22 05:12

J.G.


We can implement this in a more simple way. We can consider a infinite list where we repeat two functions: id :: a -> a, and negate :: Num a => a -> a, and use cycle :: [a] -> [a] to construct an infinite list. So cycle [id, negate] will produce a list that looks like [id, negate, id, negate, ...].

We can then use zipWith to zip the infinite list with the list of values, and use ($) :: (a -> b) -> a -> b as "zip function", so we get:

Prelude> zipWith ($) (cycle [id, negate]) [1,4,2,5]
[1,-4,2,-5]

The finally we can use sum :: Num a => [a] -> a to sum up these values.

So we can define the function as:

calculate :: Num a => [a] -> a
calculate = sum . zipWith ($) (cycle [id, negate])

For example:

Prelude> calculate [1,4,2,5]
-6
like image 32
Willem Van Onsem Avatar answered Dec 20 '22 06:12

Willem Van Onsem