最终我想实现一个简单的内存消息队列,它将消息存储为密钥元组,例如{Dst-IP,Dst-Port {CreationTime,MessageList}}其中特定目标IP地址和目标端口的所有未来消息都应附加到MessageList。
我考虑过调查Data.PSQueue(或者可能是Data.Map)。在上面的示例中,Dst-IP,Dst-Port可能是关键,而CreationTime可能是优先事项。 (我还不知道实际的MessageList是什么,但不知怎的,我必须开始看看。)
从PSQ开始,我甚至没有超越类型的最初障碍。根据我如何修改下面的代码段,我得到各种错误(使用查找函数或使用print函数),这些错误都类似于
Couldn't match expected type `IO t0'
with actual type `PSQ.PSQ k0 p0 -> Maybe p0'
或类似的。我怎样才能解决这个初始问题? 有没有比Data.PSQueue更适合我的要求的东西?
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad
import Control.Monad.State.Strict
import System.CPUTime
import qualified Data.PSQueue as PSQ
--import Language.Haskell.Pretty
main = do
time <- getCPUTime
let q = PSQ.singleton "msg" time
r <- PSQ.lookup "msg"
print (r)
答案 0 :(得分:4)
你写过r <- PSQ.lookup "msg"
。 <-
是从一个do-notation块中提取 monadic值的语法。您应该使用let r = ...
,语法来绑定纯值。
您还忘记了队列参数本身。这是错误消息告诉您的内容:<-
的右侧必须为某些 a 的IO a
类型,而是来自{PSQ k p
的函数{1}}查找结果(Maybe p
)。
完成这两项修正后,更正后的行为let r = PSQ.lookup "msg" q
。
也许您想要的是State monad,其中PSQ
为州;例如StateT PSQ IO
。这将允许您重写您的代码段,如下所示:
main :: IO ()
main = flip runStateT PSQ.empty $ do
time <- liftIO getCPUTime
modify $ PSQ.insert "msg" time
r <- gets $ PSQ.lookup "msg"
liftIO . print $ r
如果您打算编写并发程序,最佳解决方案可能是包含MVar
的{{1}}或TVar
。
您可能还对fingertree-psqueue包感兴趣,该包是基于指树的优先搜索队列的实现。我没有使用它或你正在考虑的PSQueue包,但它似乎更积极地维护。