需要帮助来理解 `liftBase` 的用法

bmk*_*bmk 3 haskell

我目前正在阅读(出于自学目的)Bryan O'Sullivan 的流行pool 的源代码。

我在函数中有一个问题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)
Run Code Online (Sandbox Code Playgroud)

我遇到问题的线路是

...
resource <- liftBase . join . atomically $ do
...
Run Code Online (Sandbox Code Playgroud)

为什么这里使用liftBasenecessary?我们也可以这样写吗

...
resource <- join . atomically $ do
...
Run Code Online (Sandbox Code Playgroud)

编译器接受这两个版本。我在这里错过了一些琐碎的事情或者为什么liftBase这里是必要的?

预先感谢您的提示!

Mic*_*man 5

我想我对此负有责任。不,它在那里没有任何意义,可以将其删除。我认为在进行一些重构之前这是必要的。您可以发送拉取请求并成为很棒的库的一部分:)


Yur*_*ras 5

它是一件历史文物。最初只有withResource函数,它之所以被使用 liftBase是因为它存在于MonadControlIO类中。然后代码被提取到takeResource,但liftBase仍然存在。