How to sort a list [MVar a] using a values?
How can sort a [MVar a] list? using a as the element to compare in the sort. E.g:
sortList :: [MVar Int] -> [MVar Int]
I cannot think a ways without breaking other threads.
Update: I need to sort the list, because I want to implement a reference count like MVar and return always the one with least references.开发者_Python百科 Something like:
getLeastUsed :: [MVar Int] -> MVar Int
getLeastUsed = head . sortList
And in the thread I want to increase the 'Int'.
Update: I was notice by answers that the rigth signature need IO because MVar
First of all, your type signature is impossible; reading an MVar
is not referentially transparent (as should hopefully be obvious--that's what they're for!). This has two consequences:
- Your sort function must return an
IO
action - The list will be sorted according to the values seen when each
MVar
was read; not only may it be invalid by the time you use the list, it may change halfway through such that the first value is out of date before you read the last value.
The former is unavoidable, and assuming the latter is acceptable for your purposes, you can do essentially what @hammar demonstrated.
However, given that the sorting will be quickly out of date, and that you seem to be mostly interested in the least element, you might find something like this more directly useful since there's little use to sorting otherwise:
import Control.Applicative
import Data.List
import Data.Ord
leastUsed :: [MVar Int] -> IO (MVar Int)
leastUsed vars = fst . minimumBy (comparing snd) . zip vars <$> mapM readMVar vars
The simplest approach would probably be to do a decorate-sort-undecorate where you first read out all the current values of the MVars and then sort using those as keys.
import Data.List (sortBy)
import Data.Ord (comparing)
sortList :: [MVar Int] -> IO [MVar Int]
sortList vars = do
currentValues <- mapM readMVar vars
return . map snd . sortBy (comparing fst) $ zip currentValues vars
Note that the resulting list may not be completely sorted since the values of the MVars may have changed since they were read. If you care about this, however, you should probably use a single MVar for the whole list.
精彩评论