Looking for a purely functional replacement for mutable vectors, but all are at least 100 times slower. Any alternative?

It is a little hard to see exactly what use case you are simplifying. Two features stand out:

One is that in every case except the mutable vector case you are growing the structure by repeated snoc-ing. With mutable vectors you use MVec.new. If there is to be any similarity, you should begin with an initialized 'purely functional replacement' that is built however one builds such things.

The second is that you seem to be envisaging a process of 'updates' on the initial vector or vector-substitute. The question is: what is the type of the source of this information? As it happens you use a Haskell list in all these cases, with the understanding the the nth position should be altered to agree with the nth position in the linked list.

We thus arrive at the following 'equivalent' linked-list program:

    list_test' size = update initialized_list
      where
      update = zipWith (\a b -> a) change_table
      change_table = enumFromTo (0::Int) (size-1)
      initialized_list = repeat (0::Int)

and the following persistent vector program:

    uvec_test' size = update initial
      where 
      update = UVec.zipWith (\a b -> a) changes 
      changes = UVec.enumFromStepN (0::Int) 1 size
      initial = UVec.replicate size (0::Int)

Unsurprisingly, building a linked list is a little clumsy by comparison with an unboxed array, but mutation slows things down:

    benchmarking tree/list
    time                 1.560 ms   (1.546 ms .. 1.576 ms)
                         0.999 R²   (0.999 R² .. 1.000 R²)
    mean                 1.553 ms   (1.542 ms .. 1.564 ms)
    std dev              35.37 μs   (29.81 μs .. 42.24 μs)
    variance introduced by outliers: 11% (moderately inflated)

    benchmarking tree/uvec
    time                 119.0 μs   (118.2 μs .. 119.9 μs)
                         0.999 R²   (0.999 R² .. 1.000 R²)
    mean                 119.9 μs   (118.9 μs .. 120.9 μs)
    std dev              3.323 μs   (2.613 μs .. 4.229 μs)
    variance introduced by outliers: 24% (moderately inflated)

    benchmarking tree/mvec
    time                 170.5 μs   (168.4 μs .. 172.8 μs)
                         0.999 R²   (0.998 R² .. 1.000 R²)
    mean                 169.3 μs   (168.0 μs .. 171.0 μs)
    std dev              5.000 μs   (3.666 μs .. 8.189 μs)
    variance introduced by outliers: 25% (moderately inflated)

This list is 1/10th as fast, not so slow it cant be completed. The mutation is a waste of time.

/r/haskell Thread