如何使用值对列表[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
答
最简单的方法很可能是做装修排序,去除装饰您第一次读出的所有电流值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作为整个列表。
我同意这些观点。我注意到IO的后果,但你使用是我需要的。 – Zhen
@ Zhen:请注意,'()'只是'fmap'的同义词,对于'Monad',表达式'f x'等价于'do {x'