В настоящее время я играю с библиотекой Bryan O'Sullivan resource-pool и задаю вопрос о расширении withResource
.
Я хочу изменить подпись функции withResource
от (MonadBaseControl IO m) => Pool a -> (a -> m b) -> m b
до (MonadBaseControl IO m) => Pool a -> (a -> m (Bool, b)) -> m b
.
То, что я хочу достичь, заключается в том, что действие должно возвращать кортеж (Bool, b)
, где булевское значение указывает, должен ли заемный ресурс
возвращаться в пул или уничтожаться.
Теперь моя текущая реализация выглядит следующим образом:
withResource :: forall m a b. (MonadBaseControl IO m) => Pool a -> (a -> m (Bool, b)) -> m b
{-# SPECIALIZE withResource :: Pool a -> (a -> IO (Bool,b)) -> IO b #-}
withResource pool act = fmap snd result
where
result :: m (Bool, b)
result = control $ \runInIO -> mask $ \restore -> do
resource <- takeResource pool
ret <- restore (runInIO (act resource)) `onException`
destroyResource pool resource
void . runInIO $ do
(keep, _) <- restoreM ret :: m (Bool, b)
if keep
then liftBaseWith . const $ putResource pool resource
else liftBaseWith . const $ destroyResource pool resource
return ret
И у меня есть ощущение, что это не так, как должно выглядеть...
Возможно, я не использую API MonadBaseControl
API.
Что вы, ребята, думаете об этом и как я могу улучшить его, чтобы быть более идиоматичным?