Вы бы лучше удаление файла и просто восстанавливается, если он не существует:
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
Это позволяет избежать состояния гонки кого-то удалить файл между вашим проверяет, существует ли он и удаляет его. В вашем случае это может быть неважно, но это хорошая практика.
Обратите внимание на строку import Prelude hiding (catch)
- это потому, что прелюдия содержит более старые функции из обработки исключений, которые теперь устарели в пользу Control.Exception, которая также имеет функцию с именем catch
; строка импорта просто скрывает прелюдию catch
в пользу Control.Exception.
Тем не менее, это все еще оставляет более фундаментальный основной вопрос: как вы записываете условные обозначения в IO
?
Ну, в данном случае, это будет достаточно просто сделать
when fileExists $ removeFile filename
(с использованием Control.Monad.when). Но это полезно здесь, как это обычно бывает в Haskell, чтобы посмотреть на типы.
Обе ветви условного типа должны иметь одинаковый тип. Поэтому заполнить
if fileExists
then removeFile filename
else ???
мы должны посмотреть на тип removeFile filename
; независимо от того, ???
, он должен иметь тот же тип.
System.Directory.removeFile имеет тип FilePath -> IO()
, поэтому removeFile filename
имеет тип IO()
. Таким образом, мы хотим, чтобы действие IO было результатом типа ()
, который ничего не делает.
Ну, цель return
является построение действия, которое не имеет никакого эффекта, а просто возвращает значение константы, и return()
имеет правильный тип для этого: IO()
(или в более общем плане, (Monad m) => m()
). Таким образом, ???
- это return()
(который вы можете видеть, что я использовал в моем улучшенном фрагменте выше, ничего не делать, когда терпит неудачу, потому что файл не существует).
(Кстати, теперь вы должны быть в состоянии осуществить when
с помощью return()
, это очень просто :))
Не волнуйтесь, если вам трудно попасть в путь Haskell вещей вначале - это будет естественно во времени, и когда это произойдет, это очень полезно. :)
Функция 'doesFileExist' действительно является приглашением к условиям гонки. Он не должен существовать. – augustss
@augustss: Как насчет того, чтобы мы просто переименовали его в 'didFileExistLastTimeIChecked'? –
Я предлагаю 'didFileNotNeverExist'. – ehird