@OP perhaps there’s a comparison bug in withdraw(): if (a.balance <= amount)
I've caught unbalanced parens:
forkIO (atomically (transfer req.from req.to req.amount)