2010-10-13 13 views
64

In quali situazioni è necessario utilizzare liftIO? Quando sto usando ErrorT String IO, la funzione lift funziona per sollevare azioni IO in ErrorT, quindi liftIO sembra superfluo.Haskell: lift vs liftIO

risposta

75

lift solleva sempre dallo strato "precedente". Se è necessario sollevare dal secondo livello, è necessario lift . lift e così via.

D'altra parte, liftIO si solleva sempre dallo strato IO (che, quando presente, è sempre nella parte inferiore della pila). Quindi, se hai più di 2 strati di monadi, apprezzerai lo liftIO.

Confrontare il tipo dell'argomento nei seguenti lambda:.

type T = ReaderT Int (WriterT String IO) Bool 

> :t \x -> (lift x :: T) 
\x -> (lift x :: T) :: WriterT String IO Bool -> T 

> :t \x -> (liftIO x :: T) 
\x -> (liftIO x :: T) :: IO Bool -> T 
+26

Generalmente userò 'liftIO' per sollevare il livello IO anche se' lift' è sufficiente, perché quindi posso cambiare lo stack monad e il codice funziona ancora. –

+11

@John: buon punto. E inoltre rende ovvio che stai sollevando IO e non qualsiasi altra monade. –

28

liftIO è solo una scorciatoia per l'IO Monade, a seconda di quale la Monade si è in sostanza, liftIO equivale all'utilizzo di un numero variabile di ascensori . All'inizio questo potrebbe sembrare ridondante, ma l'uso di liftIO ha un grande vantaggio: rende il tuo codice IO indipendente dalla costruzione Monad in modo da poter riutilizzare lo stesso codice indipendentemente dal numero di layer di Monad che è stato costruito (questo è abbastanza importante quando si scrive un trasformatore monad).

Da un lato, liftIO non arriva gratis, come fa il sollevatore: i trasformatori Monad che si stanno utilizzando devono essere supportati, ad es. la Monade in cui ti trovi deve essere un'istanza della classe MonadIO, ma al giorno d'oggi la maggior parte dei Monade lo fanno (e, naturalmente, il type-checker controllerà questo per te in fase di compilazione: questa è la forza di Haskell!).