Одна потенциальная проблема с (//) состоит в том, что требуется поиск по списку, чтобы найти значение для каждого элемента. Если массив или список велики, это может дорого обойтись.
Другой вариант - использовать удобную функцию из Data.Vector:
modify :: Vector v a => (forall s. Mutable v s a -> ST s ()) -> v a -> v a
Это имеет возможность сделать обновление на месте, если это безопасно. Так что-то вроде
import Data.Vector.Unboxed as V
import Data.Vector.Mutable.Unboxed as M
import Data.Array.Repa as R
(///) :: Shape sh => Array sh a -> [(sh,a)] -> Array sh a
(///) arr us = R.fromVector sh . modify f $ R.toVector arr
where
sh = extent arr
f mv = forM_ us $ \(k,x) -> do
M.write mv (R.toIndex sh k) x
На своем ноутбуке я протестировал это для массива DIM1 с 1 млн. Элементов, обновив 100 записей, и получил следующие значения:
(//): 3.598973
(///): 2.0859999999999997e-3