Ответ 1
Вам лучше удалить файл и просто восстановить его, если он не существует:
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)
- это потому, что Prelude содержит более старые функции из обработки исключений, которые теперь устарели в пользу Control.Exception, которая также имеет функцию с именем catch
; строка импорта просто скрывает Prelude 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 ()
(который вы можете видеть, что я использовал в своем улучшенном фрагменте выше, ничего не делать, когда removeFile
терпит неудачу, потому что файл не существует).
(Кстати, теперь вы можете реализовать when
с помощью return ()
, это действительно просто:))
Не волнуйтесь, если вам сначала трудно проникнуть в хаскелские вещи - это со временем придет естественным образом, и когда это произойдет, это будет очень полезно.:)