Reputation: 2039
What is the best way to map across a list, using the result of each map as you go along, when your result is of a different type to the list.
for example
f :: Int -> Int -> String -> String
l = [1,2,3,4]
I would like to have something that walks along the list l and does:
f 1 2 [] = result1 => f 2 3 result1 = result2 => f 3 4 result3 ==> return result3.
I can sort of get this to work with a an accumulator, but it seems rather cumbersome. Is there a standard way to do this... or is this something for Monads??
Thanks!
NB the function above is just for illustration.
Upvotes: 1
Views: 1084
Reputation: 23955
Of course, rather than zipping, you could pass along the previous element inside the fold's accumulator. For example:
l = [1,2,3,4]
f x y = (x,y)
g b@(accum,prev) a = (accum ++ [f prev a],a)
main = print (foldl g ([],head l) (tail l))
Output:
([(1,2),(2,3),(3,4)],4)
Upvotes: 1
Reputation: 91837
This is just a fold left over the pairs in the input list:
f :: Int -> Int -> String -> String
f = undefined
accum :: [Int] -> String
accum xs = foldl (flip . uncurry $ f) "" $ zip xs (drop 1 xs)
You probably want to use Data.List.foldl'
instead of foldl
, but this is an answer that works with just Prelude.
Upvotes: 4
Reputation: 9726
Seems like a job for fold
:
func f l = foldl (\s (x, y) -> f x y s) "" (zip l (tail l))
-- just some placeholder function
f :: Int -> Int -> String -> String
f x y s = s ++ " " ++ show(x) ++ " " ++ show(y)
l = [1,2,3,4]
main = print $ func f l
prints:
" 1 2 2 3 3 4"
(if you can change the signature of f
, you can get rid of the ugly lambda that rearranges arguments)
Upvotes: 3