HASKELL STM CHECK FUNTY RETURNING UNFININADO
Pregunta
¿Hay una buena razón por la cual el check
función en el Contol.Concurent.STM
La biblioteca tiene tipo Bool -> STM a
y devuelve undefined
sobre el éxito en lugar de tener el tipo Bool -> STM ()
? La forma en que se implementa el comprobador de tipo compilación de Polity compilará un bloque de bloque de hacer con check foo
solo para fallar en tiempo de ejecución con *** Exception: Prelude.undefined
.
Solución
Parece que es una definición de marcador de posición para un GHC Primop, como la "definición" seq _ y = y
Eso es reemplazado por el compilador con el código de implementación primitivo real. los Implementación primaria de check
toma una expresión y la agrega a una lista global de invariantes como se describe en el Papel de invariants stm.
Aquí hay un ejemplo súper confundido modificado de ese papel para adaptarse al nuevo tipo de 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
Siendo realistas, esto sería útil para afirmar a los invariantes en el estado compartido, donde la falla de la afirmación podría ser un signo de una inconsistencia temporal. Es posible que desee volver a intentar con la expectativa de que ese invariante se vuelva verdadero nuevamente eventualmente, pero dado que este ejemplo termina rompiendo permanentemente al invariante, solo llama retry
por siempre y parece colgar. Consulte el documento para ver ejemplos mucho mejores, pero tenga en cuenta que el tipo ha cambiado desde su publicación.