输入与Data.PSQueue不匹配

时间:2011-12-28 23:04:12

标签: haskell

最终我想实现一个简单的内存消息队列,它将消息存储为密钥元组,例如{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)

1 个答案:

答案 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包,但它似乎更积极地维护。