Функция проверки Haskell STM возвращает неопределенную

StackOverflow https://stackoverflow.com/questions/8364903

  •  27-10-2019
  •  | 
  •  

Вопрос

Есть веская причина, почему check функция в Contol.Concurent.STM Библиотека имеет тип Bool -> STM a и возвращается undefined об успехе, а не иметь типа Bool -> STM ()? То, как он реализован, проверка типа будет компиляция блока DO check foo Только чтобы провалиться во время выполнения с *** Exception: Prelude.undefined.

Это было полезно?

Решение

Похоже, это определение заполнителя для GHC Primop, как «определение» seq _ y = y Это заменяется компилятором фактическим примитивным кодом реализации. А Primop реализация check принимает выражение и добавляет его в глобальный список инвариантов, как описано в Invariants Paper.

Вот сверхконтролированный пример, измененный из этой статьи, чтобы соответствовать новому типу 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 навсегда и, кажется, висит. Проверьте статью для гораздо лучших примеров, но имейте в виду, что тип изменился с момента ее публикации.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top