Reputation: 111
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
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
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