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

问题描述:

如何排序[MVar a]列表?使用a作为排序中的比较元素。例如:如何使用值对列表[MVar a]进行排序?

sortList :: [MVar Int] -> [MVar Int] 

我想不到没有打破其他线程的方式。

更新: 我需要对列表进行排序,因为我想实现像无功引用计数,并始终返回一个与至少引用。喜欢的东西:

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

而在线程我希望增加“诠释”。

更新: 我是通过回答通知,说分辩签名需要IO因为无功

首先,您的类型签名是不可能的;阅读MVar不是透明地透明的(应该很明显 - 这就是对于!)。这有两个后果:

  • 你的排序功能必须返回一个IO行动
  • 名单将根据当每个MVar读取看到的值进行排序;不仅在您使用该列表时可能无效,而且可能会在您读取最后一个值之前第一个值过期时中途改变。

前者是不可避免的,假设后者对于您的目的是可以接受的,您可以基本做到@哈马尔所展现的。

然而,鉴于排序会很快过时,而你似乎是在最小元素最感兴趣的,你可能会因为有没有多大用处,否则排序找到这样的事情更直接有用:

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 
+0

我同意这些观点。我注意到IO的后果,但你使用是我需要的。 – Zhen

+1

@ Zhen:请注意,'()'只是'fmap'的同义词,对于'Monad',表达式'f x'等价于'do {x'

最简单的方法很可能是做装修排序,去除装饰您第一次读出的所有电流值MVars,然后使用这些键作为排序。

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 

请注意,生成的列表可能未完全排序,因为MVars的值可能在读取后发生更改。但是,如果你关心这个,你应该使用一个MVar作为整个列表。