Есть ли веская причина, по которой функция check
в библиотеке Contol.Concurent.STM
имеет тип Bool -> STM a
и возвращает в случае успеха undefined
, а не тип Bool -> STM ()
? То, как это реализовано, средство проверки типов будет компилировать блок do, оканчивающийся на check foo
, только для того, чтобы во время выполнения потерпеть неудачу с *** Exception: Prelude.undefined
.
Функция проверки Haskell STM возвращает неопределенное значение
Ответы (1)
Похоже, это определение-заполнитель для GHC PrimOp, например " определение" seq _ y = y
, которое компилятор заменяет фактическим кодом реализации примитива. Реализация PrimOp check
принимает выражение и добавляет его к глобальному списку инвариантов, как описано в Бумага по инвариантам STM.
Вот супер-придуманный пример, модифицированный из этой статьи, чтобы соответствовать новому типу check
:
import Control.Concurrent.STM
data LimitedTVar = LTVar { tvar :: TVar Int
, limit :: Int
}
newLimitedTVar :: Int -> STM LimitedTVar
newLimitedTVar lim = do
tv <- newTVar 0
return $ LTVar tv lim
incrLimitedTVar :: LimitedTVar -> STM ()
incrLimitedTVar (LTVar tv lim) = do
val <- readTVar $ tv
let val' = val + 1
check (val' <= lim)
writeTVar tv val'
test :: STM ()
test = do
ltv <- newLimitedTVar 2
incrLimitedTVar ltv -- should work
incrLimitedTVar ltv -- should work still
incrLimitedTVar ltv -- should fail; we broke the invariant
На самом деле было бы полезно утверждать инварианты в общем состоянии, когда сбой утверждения может быть признаком временной несогласованности. Затем вы можете повторить попытку, ожидая, что этот инвариант в конечном итоге снова станет истинным, но поскольку этот пример завершается необратимым нарушением инварианта, он просто вызывает retry
навсегда и, похоже, зависает. Ознакомьтесь с документом, чтобы найти гораздо лучшие примеры, но имейте в виду, что шрифт изменился с момента его публикации.
check True >>= writeTVar t
пройдет проверку типов, но вызовет ошибку времени выполнения. Я утверждаю, что приведенный выше код не должен проверять тип, если только t
не является довольно бесполезным типом TVar ()
.
- person John F. Miller; 03.12.2011
Bool -> STM ()
.
- person acfoltzer; 03.12.2011
check
, описанный в Документ по инвариантам STM теперь называетсяalwaysSucceeds
. Мне непонятно, что делает текущийcheck
. - person acfoltzer   schedule 03.12.2011check b = if b then return undefined else retry
Я утверждаю, что следует читатьcheck b = if b then return () else retry
- person John F. Miller   schedule 03.12.2011