2011-12-03 13 views
9

C'è una buona ragione per cui la funzione check nella libreria Contol.Concurent.STM è di tipo Bool -> STM a e restituisce undefined in caso di successo piuttosto che avere il tipo Bool -> STM()? Il modo in cui viene implementato il controllo di tipo comporrà un blocco do che termina con check foo solo per fallire in fase di esecuzione con *** Exception: Prelude.undefined.funzione di controllo Haskell STM restituisce undefined

+0

Questa è una buona domanda; sembra che il 'check' descritto nella [carta invarianti STM] (http://research.microsoft.com/en-us/um/people/simonpj/papers/stm/stm-invariants.pdf) sia ora chiamato' alwaysSucceeds'. Non mi è chiaro quale sia il "controllo" attuale. – acfoltzer

+0

Sì, non ho idea di quale possa essere lo scopo di averlo. Un po 'curioso ora. –

+0

'check b = se b poi restituisce undefined else retry' dichiaro che dovrebbe leggere' check b = if b then return() else retry' –

risposta

5

Sembra che sia una definizione segnaposto per un GHC PrimOp, come la "definizione" seq _ y = y che viene sostituito dal compilatore con il codice vero e primitivo implementazione. PrimOp implementation of check prende un'espressione e la aggiunge a un elenco globale di invarianti come descritto in STM invariants paper.

Ecco un esempio di super-artificiosa modificata da quella carta in base al nuovo tipo di 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 

Realisticamente, questo sarebbe utile per far valere invarianti sullo stato condiviso in cui in mancanza l'affermazione potrebbe essere un segno di un'incoerenza temporanea. Potresti quindi riprovare con l'aspettativa che l'invariante possa diventare di nuovo vero alla fine, ma poiché questo esempio finisce per rompere definitivamente l'invariante, chiama semplicemente retry per sempre e sembra bloccarsi. Controlla la carta per esempi molto migliori, ma tieni presente che il tipo è cambiato dalla sua pubblicazione.

+0

Capisco come funziona la verifica. Non capisco perché sia ​​scritto in modo tale che 'check True >> = writeTVar t' passerà il controllo del tipo, ma causerà un errore di runtime. Asserisco che il codice sopra dovrebbe fallire nel controllo del tipo a meno che 't' sia il tipo piuttosto inutile' TVar() '. –

+0

Ahhh, pensavo che la domanda fosse più nella direzione di "se questo è tutto il codice è, qual è il punto?" Sono d'accordo che sembra che il tipo dovrebbe essere 'Bool -> STM()'. – acfoltzer

Problemi correlati