【发布时间】:2013-02-06 14:44:21
【问题描述】:
在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 k v = Cache (MVar (M.Map k v))
现在我想要一个带有签名的新 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 中,而 runIdentityK 在 Proxy p => p k v k v IO r monad 中。当然,我可以将 readMVar 提升到这个代理单子中,因为它是 IO 上的转换器,但我找不到合适的组合器。
【问题讨论】:
-
与 Chris Dueck 的版本相比,Petr 版本的死锁也更安全!想象一下
request key也尝试访问同一个缓存。
标签: haskell