Mr. Moose
Mr. Moose

Reputation: 111

How to access the next element when using the map function?

I am trying to apply a function on each element of a list in haskell. Therefore I am using the map function. My code should add the value of the next element to the current element.

So I think my code should look somehow like this:

test :: [Rational]
test = map (\x -> x % {-somehow get next element -}) listT

listT is an infinite list of type Int.

But how do I "access" the next value? Thx for your help

Upvotes: 3

Views: 602

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476709

You can make use of zipWith and zip the list with its tail:

mapWithNext :: [Rational]
mapWithNext = zipWith (\x1 x2 -> …) listT (tail listT)

Upvotes: 3

Will Ness
Will Ness

Reputation: 71075

To access the next element, map on tails instead:

mapWithNext op xs = map g (tails xs)
  where
  g (x:y:_) = Just (op x y)
  g _       = Nothing

since when there's no next element, your op can't be applied, though it will only happen with the finite lists. You might know that the input lists will be infinite, but your type doesn't, so it's better to be on the safe side.

You might want to add a post-processing step to get rid of the final Nothing(s) and extract the Just values. catMaybes :: [Maybe a] -> [a] seems applicable.

Of course using zipWith(*) mentioned in the comments is cleaner and more to the point, here; but this way with tails is more versatile in general, i.e. it is easier to amend to be used with e.g. ternary op, etc.. With zipWith we'd have to use a chain of nested zipWith applications and build artificial tuples just to have access to the elements; with tails we don't need to do anything like that at all.

A combination of map (generally, foldr) with tails is actually emulating paramorphism. It has its merits so as e.g. in Common Lisp it is actually present as a library function maplist.

(*) you could say, zipWith is not map, but e.g. in Scheme it is so. There, map accepts an arbitrary number of argument lists, and a combining operation of the corresponding arity. But of course Haskell is not Scheme.

Upvotes: 6

Related Questions