簡體   English   中英

使用具有並發MVar的管道/代理

[英]Using pipes/proxies with concurrent MVars

pipes-3.1.0包的Control.Proxy教程中,作者提供了這個函數:

cache :: (Proxy p, Ord key) => key -> p key val key val IO r
cache = runIdentityK (loop M.empty) where
    loop _map key = case M.lookup key _map of
        Nothing -> do
            val  <- request key
            key2 <- respond val
            loop (M.insert key val _map) key2
        Just val -> do
            lift $ putStrLn "Used cache!"
            key2 <- respond val
            loop _map key2

因為我想要並發應用程序緩存請求,所以我有以下數據類型

newtype Cache kv = Cache (MVar (M.Map kv))

現在我想要一個帶簽名的新cache功能

cache :: (Proxy p, Ord k) => Cache k v -> k -> p k v k v IO r
cache (Cache c) k = readMVar c >>= \m -> runIdentityK $ loop m k
    where loop m key = case M.lookup key m of
            Nothing -> do
                val <- request key
                respond val >>= loop (M.insert key val m)
            Just val -> respond val >>= loop m

但是,由於readMVar位於IO monad中,因此無法進行類型readMVar ,而runIdentityK位於Proxy p => pkvkv IO r monad中。 當然,我可以將readMVar提升到這個代理monad中,因為它是IO上的轉換器,但我找不到合適的組合器。

解決方案是簡單的lift 我曾經想過要用它,但顯然沒有用力。 這是我所需cache的粗略的類型檢查版本

cache = runIdentityK . loop
    where loop (Cache c) key = lift (takeMVar c) >>= \m -> case M.lookup key m of
            Nothing -> do
                val <- request key
                lift . putMVar c $ M.insert key val m
                respond val >>= loop (Cache c)
            Just val -> do
               lift $ putMVar c m 
               respond val >>= loop (Cache c)

它就像添加lift一樣簡單。 但是,您的實現似乎沒有按照您的意圖執行。 您只在開始時讀取了一次MVar ,然后再也不再使用它,只需在循環中傳遞更新的地圖。 如果不同的線程應該通過MVar看到更改,您還必須更新它。 一個建議(編譯,但我還沒有測試它是如何工作的):

cache :: (Proxy p, Ord k) => Cache k v -> k -> p k v k v IO r
cache (Cache c) k = runIdentityK loop k
    where 
      loop key = do
        m <- lift (readMVar c)
        case M.lookup key m of
            Nothing -> do
                val <- request key
                lift $ modifyMVar_ c (return . M.insert key val)
                respond val >>= loop
            Just val -> respond val >>= loop

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM