В библиотеке haskell stm есть функция со следующей сигнатурой типа:
alwaysSucceeds :: STM a -> STM ()
Из того, что я понимаю в STM в haskell, есть три способа, что что-то может "пойти не так" (используя этот термин свободно), в то время как выполняется STM-вычисление:
- Значение прочитанного TVar изменяется другим потоком.
- Нарушен пользовательский инвариант. Обычно это срабатывает, вызывая
retry
, чтобы начать работу. Это эффективно блокирует поток, а затем повторяет попытку после изменения TVar в считываемом наборе. - Вызывается исключение. Вызов
throwSTM
вызывает это. Этот отличается от первых двух, потому что транзакция не перезапускается. Вместо этого ошибка распространяется и либо сбой программы, либо попадает в IO-монаду.
Если они точны (а если нет, скажите, пожалуйста), я не могу понять, что может сделать alwaysSucceeds
. Функция always
, которая, по-видимому, построена поверх нее, кажется, что она может быть записана без alwaysSucceeds
как:
--This is probably wrong
always :: STM Bool -> STM ()
always stmBool = stmBool >>= check
В документации для alwaysSucceeds
указано:
alwaysSucceeds добавляет новый инвариант, который должен быть истинным при передаче alwaysSucceeds, в конце текущей транзакции и в конце каждой последующей транзакции. Если он терпит неудачу в любой из этих точек то транзакция, нарушающая ее, прерывается, и исключение возникает по инварианту.
Но поскольку аргумент имеет тип STM a
(полиморфный в a
), он не может использовать значение, которое транзакция возвращает для любой части принятия решения. Таким образом, похоже, что он будет искать различные типы сбоев, которые я перечислял ранее. Но в чем смысл? Монада STM уже обрабатывает сбои. Как его обертывание в этой функции повлияет? И почему переменная типа a
отбрасывается, что приводит к STM ()
?