Downside of returning release action from acquire in bracket?

Say I want to do actions before/after a given IO action, where the “after” action needs info from the “before” action, but the IO action doesn’t need it. The canonical approach would be

let before = do
      result <- query
      set result
      pure result
    after result = do
      unset result
in bracket before after (\_ -> action)

What’s the downside of just doing

let setup = do
      result <- query
      set result
      pure $ unset result
in bracket setup id (\_ -> action)

The benefit of the second approach is I don’t have to manually pass the information needed to run the post action. But what’s the downside? Would the returned action keep local variables alive?

1 Like

I don’t see anything immediately egregious looking at the definition for bracket and it works as expected in my limited testing. I’m curious too to see if there’s any major difference performing it either way.

EDIT: On reflection your code would be equivalent to:

let setup = do
      result <- query
      set result
      pure result
in setup >>= \res -> finally (unset res) action
1 Like

Can’t you just run finally instead?

The point of the bracket function is that you run the cleanup handler both when encountering an exception or when exiting normally. You also want to mask exceptions while acquiring the resource so you don’t accidentally leak it. That’s why it needs to be structured like that.

I don’t personally see a difference between these. The second form is a bit unusual, but they should behave the same.