2011-12-28 84 views
0

最终,我想实现一个简单的内存消息队列,它将消息存储为键元组,例如{Dst-IP,Dst-Port {CreationTime,MessageList}},其中特定目的地IP地址和目的地端口的所有未来消息应该被附加到MessageList。类型与Data.PSQueue不匹配

我想过调查Data.PSQueue(或者Data.Map)。在上面的Dst-IP示例中,Dst-Port可能是关键,而CreationTime可能是重点。 (我不知道实际的MessageList可能是什么,但不知怎的,我必须开始看到)。

从PSQ开始,我甚至没有超过类型的最初障碍。根据我如何修改下面的代码片段,我得到的各种错误(或者使用查找功能或打印功能),所有类似

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) 

回答

4

您已经写下r <- PSQ.lookup "msg"<-提取来自符号块内的monadic值的语法。您应该使用let r = ...,该语法绑定纯粹的值。

您也忘记了队列参数本身。这是错误信息告诉你的:<-的右侧必须是IO a,对于某些a,但是它是从PSQ k p到查找结果(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 

如果你打算写一个并发程序,最好的解决方案可能是一个MVarTVar包含PSQ代替。

您可能还对fingertree-psqueue软件包感兴趣,它是基于手指树的优先搜索队列的实现。我没有使用它或你正在考虑的软件包,但似乎更积极维护。

+0

谢谢。有没有什么简单的方法可以让我使用问题文本中描述的关键元组而不是简单的关键字?也许使用记录? – 2011-12-28 23:35:56

+0

难道你只是使用元组或其他数据类型(如记录)作为密钥? – ehird 2011-12-28 23:57:12