Array – how to use data Vector. Generic. Mutable?
How to sort long list data (string, floating point, etc.) read from large files
Solution
In general, how is this done
First, you need a variable vector You can gradually create this scanned file; Allocate a vector as large as you need, and increase the size and copy when space is insufficient Or you can read the entire file, count record separators, and allocate an appropriate amount of space once This is easy, but it may not be acceptable in real life (the strategy of on-demand expansion is beautiful in common; what happens if you use a language like Perl and the line you read from the file to the end of the array. Perl allocates some space for the array. When you fill it, it will increase the amount of space and allocate new space and copies.)
Anyway, I'm too lazy, so I just want to create a vector with some random numbers
We need a bunch of Libraries:
import Control.Monad import System.Random import qualified Data.Vector as IV import qualified Data.Vector.Mutable as MV import qualified Data.Vector.Generic as V import qualified Data.Vector.Algorithms.Intro as VA
We don't need all this, but we finally need it, so I thought I'd get it out
In any case, our variable vector will be a "normal" variable vector, here MV MVector.
The idea of variable vector is to create it and modify its steps. In Haskell, there are several ways to make this look pure phone code; One was made in St monad Your st action is creating a vector, modifying it, and "freezing" it into an invariant vector Internally, you use this memory location quickly - a bunch of operations at a time, but outside, you have something pure (read paper st, if you want an argument, why is it safe.)
Another way to handle variable data is to do everything in it, uh, IO, monad That's what we do here. It's the most convenient
(data.vector.mutable provides you with two predefined vector types, iovector and stvector. We are using iovector, which operates all vectors as io.)
So like the previous 8 paragraphs, we're going to create a variable vector classification Here we are:
randVector :: IO (MV.IOVector Int) randVector = do v <- MV.new 10 forM [0..9] $\x -> do r <- randomIO :: IO Int MV.write v x r return v
This is an IO operation, which returns the number in a new variable vector of 10 random numbers (random number generation can also be easily promoted to IO monad, so we do the same for convenience! It's like we're writing C, but it has better syntax and more type security.)
This is actually very difficult Sort, I import data Vector. Algorithms. Intro is basically in place for quick sorting A function called sort actually sorts (in units of variable vectors)
The action of creating random variable vectors and sorting them looks like:
sort = VA.sort =<< randVector
Now, to print it out, all we need to do is load it into an immutable vector and print it out toList. Or you can just iterate over each element and print
Here are the examples I came up with:
main = do v <- randVector VA.sort v iv <- V.unsafeFreeze v :: IO (IV.Vector Int) print . V.toList $iv
5. Unsafefreeze from data Vector. Generic (how do you interact? All vector types have the same API), and v.tolist
In any case, it is worth noting that IO is entirely for convenience Since you are building vectors from file data, it is appropriate 99% of course, you should use St. in your st action, create vectors, sort, freeze, and return the frozen version
A similar example of using stvector:
randVector :: ST s (Vector Int) randVector = do vec <- new 10 rand <- newSTRef 17 forM_ [0..9] $\index -> do randN <- readSTRef rand let randN' = (fst . next . mkStdGen) randN writeSTRef rand randN' write vec index randN' unsafeFreeze vec
Then run:
*Main> runST randVector fromList [679560,1422110406,306332632,1905242129,692062628,393451229,355476175,1240028023,873588529,1181443777] :: Data.Vector.Vector