2011-11-04 16 views
7

ho scritto la seguente funzione:GHC rifiuta il codice monad ST come non è in grado di unificare le variabili di tipo?

(.>=.) :: Num a => STRef s a -> a -> Bool 
r .>=. x = runST $ do 
v <- readSTRef r 
return $ v >= x 

ma quando ho provato a compilare ho ottenuto il seguente errore:

Could not deduce (s ~ s1) 
from the context (Num a) 
    bound by the type signature for 
      .>=. :: Num a => STRef s a -> a -> Bool 
    at test.hs:(27,1)-(29,16) 
    `s' is a rigid type variable bound by 
     the type signature for .>=. :: Num a => STRef s a -> a -> Bool 
     at test.hs:27:1 
    `s1' is a rigid type variable bound by 
     a type expected by the context: ST s1 Bool at test.hs:27:12 
Expected type: STRef s1 a 
    Actual type: STRef s a 
In the first argument of `readSTRef', namely `r' 
In a stmt of a 'do' expression: v <- readSTRef r 

chiunque può aiutare?

risposta

12

Questo è esattamente come previsto. Un STRef è valido solo in una corsa di runST. E tu provi a mettere uno STRef esterno in una nuova corsa di runST. Questo non è valido. Ciò consentirebbe effetti collaterali arbitrari nel codice puro.

Quindi, quello che si prova è impossibile da raggiungere. Dal design!

7

è necessario rimanere all'interno del contesto ST:

(.>=.) :: Ord a => STRef s a -> a -> ST s Bool 
r .>=. x = do 
v <- readSTRef r 
return $ v >= x 

(E come sottolinea Hammar, per usare >= è necessario il Ord typeclass, che Num non fornisce.)

+1

Si noti che questo ancora non scriverò il controllo, poiché il vincolo dovrebbe essere 'Ord', non' Num'. – hammar

+0

Grazie per averlo notato. – dave4420