Type mismatch with Data.PSQueue

瘦欲@ 提交于 2020-01-07 04:00:49

问题


Eventually I want to achieve a simple in memory message queue that stores messages as key-tuples e.g. {Dst-IP, Dst-Port {CreationTime, MessageList}} where all future messages for a specific Destinations IP address and Destination Port should be appended to MessageList.

I thought about invetigating Data.PSQueue (or maybe Data.Map). In the example above the Dst-IP, Dst-Port could be the key whilst CreationTime could be the priority. (I have no idea yet what the actual MessageList could be, but somehow I have to start and see).

Starting with PSQs I do not even get past the initial hurdle of types. Depending on how I modify the below snippet, I get various errors (either with the lookup function or with the print function) that all resemble

Couldn't match expected type `IO t0'
                with actual type `PSQ.PSQ k0 p0 -> Maybe p0'

or similar. How can I get past this initial problem? Is there anything that fits my requirements better than 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:


You've written r <- PSQ.lookup "msg". <- is the syntax to extract a monadic value from within a block of do-notation. You should instead use let r = ..., the syntax to bind pure values.

You also forgot the queue parameter itself. This is what the error message is telling you: the right-hand side of <- has to be of type IO a for some a, but instead it's a function from a PSQ k p to the result of a lookup (Maybe p).

After those two fixes, the corrected line is let r = PSQ.lookup "msg" q.

Perhaps what you instead want is a State monad with a PSQ as the state; e.g. StateT PSQ IO. This would let you rewrite your snippet as follows:

main :: IO ()
main = flip runStateT PSQ.empty $ do
  time <- liftIO getCPUTime
  modify $ PSQ.insert "msg" time
  r <- gets $ PSQ.lookup "msg"
  liftIO . print $ r

If you're intending to write a concurrent program, the best solution is probably an MVar or TVar containing a PSQ instead.

You might also be interested in the fingertree-psqueue package, an implementation of priority search queues based on finger trees. I haven't used it or the PSQueue package you're considering, but it seems to be more actively maintained.



来源:https://stackoverflow.com/questions/8662278/type-mismatch-with-data-psqueue

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!