The Data.Vector API provides an efficient backpermute function, which basically applies a index-mapping σ-vector to a vector v, i.e. v'[j] = v[σ[j]].
Or expressed in list-syntax (for simplicity):
backpermute :: [Int] -> [a] -> [a]
backpermute σ v = map (v !!) σ
Which can have O(n) complexity if !! has O(1) complexity (which I assume for Data.Vector). Now I want the inverse “forward” permute operation (or alternatively a function for inverting the σ-vector itself), i.e. something like (again in list-syntax):
permute :: [Int] -> [a] -> [a]
permute σ = map snd . sortBy (comparing fst) . zip σ
invperm :: [Int] -> [Int]
invperm σ = permute σ [0..]
Alas, the code above is not O(n) due to sortBy. But since σ is assumed to be a permutation of a prefix of [0..] permute should be expressible as a O(n) algorithm with the Data.Vector API.
So, how can I implement an efficient O(n) permute (or alternatively an O(n) invperm) in terms of the Data.Vector.* APIs?
Monadic initialization, perhaps?