我目前正在阅读(用于自学目的)Bryan O' Sullivan受欢迎的pool
library的源代码。
我在函数takeResource
中有一个问题,我想在这里询问Haskell专家。
该函数定义为:
takeResource :: Pool a -> IO (a, LocalPool a)
takeResource pool@Pool{..} = do
local@LocalPool{..} <- getLocalPool pool
resource <- liftBase . join . atomically $ do
ents <- readTVar entries
case ents of
(Entry{..}:es) -> writeTVar entries es >> return (return entry)
[] -> do
used <- readTVar inUse
when (used == maxResources) retry
writeTVar inUse $! used + 1
return $
create `onException` atomically (modifyTVar_ inUse (subtract 1))
return (resource, local)
我遇到的问题是
...
resource <- liftBase . join . atomically $ do
...
为什么这里使用liftBase
是必要的?我们也可以写
...
resource <- join . atomically $ do
...
编译器接受这两个版本。我在这里错过了一些微不足道的事情,或者为什么liftBase
这里有必要?
提前感谢您的提示!
答案 0 :(得分:4)
我想我应该为此负责。不,它没有任何目的,它可以被删除。我认为在进行一些重构之前有必要。您可以发送拉取请求并成为令人敬畏的库的一部分:)
答案 1 :(得分:4)
这是一件历史文物。最初只有withResource
函数,而used liftBase
因为它位于MonadControlIO
类中。然后代码被提取到takeResource
,但liftBase
仍在那里。