ResourceT and deallocation variations

{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.Trans.Resource
import Control.Exception.Lifted (mask)
import Control.Monad.IO.Class
import Control.Monad.Trans.Control

data ReleaseKeyV a = ReleaseKeyV !ReleaseKey !(a -> IO ())

registerV :: MonadResource m => (a -> IO ()) -> a -> m (ReleaseKeyV a)
registerV cleanup onExc = do
    key <- register (cleanup onExc)
    return $! ReleaseKeyV key cleanup

releaseV :: (MonadBaseControl IO m, MonadIO m) => ReleaseKeyV a -> a -> m ()
releaseV (ReleaseKeyV key cleanup) value = mask $ \restore -> do
    res <- unprotect key
    case res of
        Just _ -> restore $ liftIO $ cleanup value
        Nothing -> return () -- should probably throw an error, this key was already released
        
main :: IO ()
main = do
    runResourceT $ do
        key <- registerV putStrLn "exceptional"
        releaseV key "unexceptional"
    runResourceT $ do
        key <- registerV putStrLn "exceptional"
        error "foo"
        releaseV key "unexceptional"