Si sarebbe meglio rimuovere il file e semplicemente recuperare se non esiste:
import Prelude hiding (catch)
import System.Directory
import Control.Exception
import System.IO.Error hiding (catch)
removeIfExists :: FilePath -> IO()
removeIfExists fileName = removeFile fileName `catch` handleExists
where handleExists e
| isDoesNotExistError e = return()
| otherwise = throwIO e
questo modo si evita la condizione di competizione di qualcuno l'eliminazione del file tra il codice verifica se esiste e lo elimina. Potrebbe non avere importanza nel tuo caso, ma è comunque una buona pratica.
Nota la riga import Prelude hiding (catch)
: questo perché il Preludio contiene funzioni meno recenti dalla gestione delle eccezioni che ora sono deprecate a favore di Control.Exception, che ha anche una funzione denominata catch
; la riga di importazione nasconde semplicemente il Prelude catch
in favore di Control.Exception.
Tuttavia, ciò lascia ancora la domanda di fondo più fondamentale: come si scrivono condizionali in IO
?
Beh, in questo caso, sarebbe sufficiente a fare semplicemente
when fileExists $ removeFile filename
(usando Control.Monad.when). Ma è utile qui, come di solito è in Haskell, guardare i tipi.
Entrambi i rami di un condizionale devono avere lo stesso tipo. Quindi per riempire
if fileExists
then removeFile filename
else ???
dovremmo guardare il tipo di removeFile filename
; qualunque sia lo ???
, deve avere lo stesso tipo.
System.Directory.removeFile ha il tipo FilePath -> IO()
, quindi removeFile filename
ha il tipo IO()
. Quindi quello che vogliamo è un'azione IO con un risultato di tipo ()
che non fa nulla.
Ebbene, lo scopo di return
è di costruire un'azione che non ha effetti, e solo restituisce un valore costante, e return()
ha il tipo giusto per questo: IO()
(o più in generale, (Monad m) => m()
). Quindi ???
è return()
(che puoi vedere ho usato nel mio snippet migliorato sopra, per non fare nulla quando removeFile
fallisce perché il file non esiste).
(A proposito, si dovrebbe ora essere in grado di implementare when
con l'aiuto di return()
: è molto semplice :))
Non ti preoccupare se si fatica a entrare nel modo Haskell delle cose all'inizio - arriverà naturalmente nel tempo e, quando lo farà, sarà molto gratificante. :)
La funzione 'doesFileExist' è davvero un invito alle condizioni di gara. Non dovrebbe esistere. – augustss
@augustss: che ne dici di rinominarlo in 'didFileExistLastTimeIChecked'? –
Suggerisco 'didFileNotNeverExist'. – ehird