问题
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