Уборка
Чтобы гарантировать удаление временного файла, воспользуемся функцией bracketOnError из модуля Control.Exception. Она очень похожа на bracket, но если последняя получает ресурс и гарантирует, что освобождение ресурса будет выполнено всегда, то функция bracketOnError выполнит завершающие действия только в случае возникновения исключения. Вот исправленный код:
import System.IO
import System.Directory
import Data.List
import Control.Exception
main = do
contents <– readFile "todo.txt"
let todoTasks = lines contents
numberedTasks = zipWith ( line –> show n ++ " – " ++ line)
[0..] todoTasks
putStrLn "Ваши задания:"
mapM_ putStrLn numberedTasks
putStrLn "Что вы хотите удалить?"
numberString <– getLine
let number = read numberString
newTodoItems = unlines $ delete (todoTasks !! number) todoTasks
bracketOnError (openTempFile "." "temp")
((tempName, tempHandle) –> do
hClose tempHandle
removeFile tempName)
((tempName, tempHandle) –> do
hPutStr tempHandle newTodoItems
hClose tempHandle
removeFile "todo.txt"
renameFile tempName "todo.txt")
Вместо обычного использования функции openTempFile мы заключаем её в bracketOnError. Затем пишем, что должно произойти при возникновении исключения: мы хотим закрыть и удалить временный файл. Если же всё нормально, пишем новый список заданий во временный файл; все эти строки остались без изменения. Мы выводим новые задания, удаляем исходный файл и переименовываем временный.