Skip to content

generalBracket By Design Is Not Nestable #166

@eric-corumdigital

Description

@eric-corumdigital

I am possibly misunderstanding how generalBracket works but here is my analysis.

My situation is that I want to take an AVar, do some action on the value, then put a value to the AVar and return the action result. The invariant is that if the AVar was taken then a value must be put to it, and if the AVar was not taken then a value must not be put to it. Taking the AVar must be killable.

This first example makes no attempt at bracketing but demonstrates what should happen on the happy path.

transact ∷ ∀ a b. (a → Aff (Tuple a b)) → AVar a → Aff b
transact f v = do
  a ← AVar.take v
  Tuple a' b ← f x
  AVar.put a' v
  pure b

There are several places in which a failure or kill breaks the invariant. Adding brackets, first to deal with taking the AVar must be killable:

transact f v =
  generalBracket
  (pure unit)
  { killed: \_ _ → pure unit
  , failed: \_ _ → pure unit
  , completed: …
  }
  (\_ → AVar.take v) 

And now this is stuck. There is no way to return the result from completed, so there is no way to continue transact given that taking the AVar succeeded.

In other words, brackets are not nestable. Say they were, however, this is what could be done:

transact f v =
  generalBracket (pure unit)
  { killed: \_ _ → pure unit
  , failed: \_ _ → pure unit
  , completed: \a _ →
      generalBracket (pure unit)
      { killed: \_ _ → AVar.put a v
      , failed: \_ _ → AVar.put a v
      , completed: \(Tuple a' b) _ → invincible (AVar.put a' v $> b)
      }
      (f a)
  }
  (\_ → AVar.take v) 

This assumes the typing:

generalBracket ∷ ∀ a b c. Aff a → BracketConditions a b c → (a → Aff b) → Aff c

type BracketConditions a b c =
  { killed ∷ Error → a → Aff Unit
  , failed ∷ Error → a → Aff Unit
  , completed ∷ b → a → Aff c
  }

If there is another way to implement this program I just am not seeing it right now.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions