Daml indexed equivalent

Is there a nicer way to do the equivalent of Haskell indexed :: [a] -> [(Int, a)] other than:

zip [0..length a] a

This is somewhat similar to Map over list with running index. I think your solution is fine but length traverses the list once and then zip does again so it’s not super efficient.

For a more efficient solution either use the zipWith function from the linked post or if you really want to squeeze every last interpreter cycle out of it, inline the function into zipWith:

indexed : [a] -> [(Int, a)]
indexed as =
  fst $ foldr (\a (bs, i) -> ((i, a) :: bs, i + 1)) ([], 0) as

That said, while I think the switch to the efficient mapWithIndex will bring measurable improvements (in macrobenchmarks, always hard to say how it translates to a full app), the inlining benefits should be tiny and I personally wouldn’t bother with that unless you have the benchmarks to back it up.

1 Like

Shouldn’t this be instead:

indexed as = fst $ foldr (\a (bs, i) -> ((i, a) :: bs, i - 1)) ([], length as - 1)

ah right sorry wrong direction, you could try

indexed as =
  reverse $ fst $ foldl (\(bs, i) a -> ((i, a) :: bs, i + 1)) ([], 0) as

which might be a tiny bit faster but tbh I doubt at that point it matters much compared to the zip solution.