Haskell : reference to previously updated elements of list within the update function
haskell, state
Solution
This trick is related to tying the knot: we'll use the answer while computing the answer. For the purposes of illustration, I'll use `type Book = Int` instead.
updateShelf :: Shelf -> Shelf
updateShelf shelf = answer where
answer = zipWith updateBook shifted shelf
shifted = replicate 3 Nothing ++ map Just answer
-- some stupid implementation just for illustration
updateBook :: Maybe Book -> Book -> Book
updateBook Nothing current = current + 1
updateBook (Just threeBack) current = current + threeBack + 1
Now, in `ghci`, we can verify that `updateShelf` is really using the updated versions:
*Main> updateShelf [1,10,100,1000,10000]
[2,11,101,1003,10012]
As you can see, the first three are `1+1`, `10+1`, and `100+1`, and the remaining two are `1000+(1+1)+1` and `10000+(10+1)+1`, and are therefore using the updated previous values, just as you'd hope.
Problem
Say I have the following definitions ``` data Book = Book {id :: Int, title :: String} type Shelf = [Book] ``` Assuming I have a hypothetical function (upd is for update) ``` updShelf :: Shelf -> Shelf updShelf all@(book : books) = updBook book : updShelf books ``` All fine so far. Now let's say the updateBook function needs to refer to the updated book three books before it i.e updateBook for book at position 5 in bookshelf need to refer to book at position 2 (assume first three books need no such reference to update). No problem, I say, and modify my code as such: ``` updShelf :: Shelf -> Shelf updShelf all@(book : books) prevBook = updBook book prevBook : updShelf books where prevBook = ??? ``` What I need help is with is the prevBook function. Although I am not even sure if I am approaching this problem the right way. So, if you guys have any better suggestion to approach this problem differently, it would be highly appreciated EDIT: Thomas M. DuBuisson: Your solution won't work for me. Here's why: Assume initial shelf (all) state as ``` Book {id=1, title="a"} Book {id=2, title="b"} Book {id=3, title="c"} Book {id=4, title="d"} Book {id=5, title="e"} Book {id=6, title="f"} Book {id=7, title="g"} Book {id=8, title="h"} ``` then (drop 3 partialUpdate) is (using only ids rather than entire book statement): ``` updBook 4 updBook 5 updBook 6 updBook 7 updBook 8 ``` zipWith' ($) (drop 3 partialUpdate) (all) is : ``` updBook 4 1 updBook 5 2 updBook 6 3 updBook 7 4 -> YIKES! Older version of book 4! updBook 8 5 -> YIKES! Older version of book 5! ``` In my case, I need books 7 and 8 to be updated against already updated versions of book 4 and 5,not the un-updated ones. I hope you understand what I mean to convey.