简体   繁体   English

如何使用值对列表[MVar a]进行排序?

[英]How to sort a list [MVar a] using a values?

How can sort a [MVar a] list? 如何对[MVar a]列表进行排序? using a as the element to compare in the sort. 使用a作为元素进行排序比较。 Eg: 例如:

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. 更新:我需要对列表进行排序,因为我想实现像MVar这样的引用计数,并始终返回引用最少的那个。 Something like: 就像是:

getLeastUsed :: [MVar Int] -> MVar Int
getLeastUsed = head . sortList

And in the thread I want to increase the 'Int'. 并在线程中我想增加'Int'。

Update: I was notice by answers that the rigth signature need IO because MVar 更新:答案中我注意到,严格签名需要IO,因为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 !). 读取MVar并不是参照透明的(希望应该很明显-这就是他们的目的 !)。 This has two consequences: 这有两个结果:

  • Your sort function must return an IO action 您的排序功能必须返回IO操作
  • The list will be sorted according to the values seen when each MVar was read; 该列表将根据读取每个MVar时看到的值进行排序。 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. 前者是不可避免的,并且假设后者对于您的目的是可以接受的,那么您基本上可以执行@hammar演示的操作。

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. 最简单的方法可能是做一个decorate-sort-unecorate,您首先要读出MVar的所有当前值,然后使用这些值作为键进行排序。

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. 请注意,由于MVars的值自读取以来可能已更改,因此结果列表可能未完全排序。 If you care about this, however, you should probably use a single MVar for the whole list. 但是,如果您对此感到担心,则可能应该对整个列表使用单个MVar。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM