ich zur Zeit mit dem Bryan O'Sullivan resource-pool Bibliothek spielte und haben eine Frage in Bezug auf die withResource
Funktion erstreckt. Ich möchte die Signatur der withResource
Funktion (MonadBaseControl IO m) => Pool a -> (a -> m b) -> m b
-(MonadBaseControl IO m) => Pool a -> (a -> m (Bool, b)) -> m b
ändern.
Was ich erreichen möchte ist, dass die Aktion (Bool, b)
Tupel zurückgeben sollte, wo der Booleschen Wert zeigt an, ob die geliehene Ressource sollte wieder in den Pool oder zerstört gestellt werden.Arbeiten mit dem `MonadBaseControl` API
Jetzt ist meine aktuelle Implementierung sieht wie folgt aus:
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
Und ich habe das Gefühl, dass dies nicht der Fall ist, wie es soll aussehen ... Vielleicht bin ich nicht die MonadBaseControl
API direkt verwenden. Was denkst du darüber und wie kann ich es verbessern, um idiomatischer zu werden?
Ein flüchtiger Blick sieht gut aus. Was stört dich daran? – luqui
@luqui Was mich ein bisschen stört ist, dass ich 'runInIO' zweimal ausführen muss, was zu einem ausführlicheren Code führt. Gibt es eine bessere Möglichkeit, das "ret" (das Ergebnis des ersten 'runInIO'-Aufrufs) in der IO-Monade auszupacken? – bmk