1

I am trying to update (i.e., replace an element) of a list in a list comprehension, and then use the updated list for the next iteration of the list comprehension.

For example, in this code:

let n_nums = [replaceAt n (nums!!(n + 1)) nums | n <- [0..length nums]]

replaceAt always works on nums, whereas I would like it to work on n_nums from the second iteration, and then on the newly updated list on the third iteration, and so on. What is a smart way to do that?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
razumichin
  • 84
  • 1
  • 3
  • 6
  • 1
    All Haskell's objects are *immutable* so you can not *edit* a list, you make a new one. – Willem Van Onsem Feb 26 '20 at 11:02
  • 1
    Can you explain exactly *what* you want. As in what list do you want to generate. Not *how* you want to do that? – Willem Van Onsem Feb 26 '20 at 11:03
  • Thanks, I still need to wrap my head about many concepts in Haskell. In the example above, if `nums = [0,1,2,3,4,5]`, I would like the final result to be `n_nums = [1,2,3,4,5,6]`. But this is just a simple example - I would like to apply the same principle to other lists completely different from `nums`. – razumichin Feb 26 '20 at 11:12
  • 4
    That looks like a `map (1+) nums` – Willem Van Onsem Feb 26 '20 at 11:13
  • 1
    If you however aim to "shift" the list one to the left, it is not entirely clear to me where the `6` comes from. – Willem Van Onsem Feb 26 '20 at 11:23
  • Thanks, I should be able to make it work with `map`. The example I wrote is only a general example, I don't need to work on it specifically. – razumichin Feb 26 '20 at 11:29

1 Answers1

1

Can't be done with list comprehensions (unless zip is used -- see below).

Use scanl :: (b -> a -> b) -> b -> [a] -> [b] or iterate :: (a -> a) -> a -> [a] or mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y]) and other related state-passing higher-order functions, for that. iterate with (!! n) over its result is probably the best fit here. Or scanl over the list of indices [1..n]. Or something like that.

Of course hand-coded recursive code is always an option.

On the second thought, using zip, the input can be paired up with the result shifted by one notch through the use of tail, then this zipped result can be drawn from in a list comprehension ... to create the result!

See the supposedly impossible definition of sum in terms of map (which also uses zip and last).

Will Ness
  • 70,110
  • 9
  • 98
  • 181