Изучай Haskell во имя добра! (Липовача) - страница 140

.

Вот код функции >view:

>view :: [String] –> IO ()

>view [fileName] = do

>   contents <– readFile fileName

>   let todoTasks = lines contents

>       numberedTasks = zipWith (\n line –> show n ++ " – " ++ line)

>                       [0..] todoTasks

>   putStr $ unlines numberedTasks

Программа, которая удаляла задачу из списка, производила практически те же самые действия: мы отображали список задач, чтобы пользователь мог выбрать, какую из них удалить. Но в этой функции мы просто отображаем список.

Ну и наконец реализуем функцию >remove. Функция будет очень похожа на программу для удаления элемента, так что если вы не понимаете, как работает функция удаления, прочитайте пояснения к её определению. Основное отличие – мы не задаём жёстко имя файла, а получаем его как аргумент. Также мы не спрашиваем у пользователя номер задачи для удаления – его мы также получаем в виде аргумента.

>remove :: [String] -> IO ()

>remove [fileName, numberString] = do

>   contents <- readFile fileName

>   let todoTasks = lines contents

>       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 fileName

>            renameFile tempName fileName)

Мы открываем файл, полное имя которого задаётся в идентификаторе >fileName, открываем временный файл, удаляем строку по индексу, записываем во временный файл, удаляем исходный файл и переименовываем временный в >fileName. Приведём полный листинг программы во всей её красе:

>import System.Environment

>import System.Directory

>import System.IO

>import Control.Exception

>import Data.List


>dispatch :: String -> [String] -> IO ()

>dispatch "add" = add

>dispatch "view" = view

>dispatch "remove" = remove


>main = do

>   (command:argList) <- getArgs

>   dispatch command argList


>add :: [String] -> IO ()

>add [fileName, todoItem] = appendFile fileName (todoItem ++ "\n")


>view :: [String] -> IO ()

>view [fileName] = do

>   contents <- readFile fileName

>   let todoTasks = lines contents

>       numberedTasks = zipWith (\n line -> show n ++ " – " ++ line)

>                       [0..] todoTasks

>   putStr $ unlines numberedTasks


>remove :: [String] -> IO ()

>remove [fileName, numberString] = do

>   contents <- readFile fileName

>   let todoTasks = lines contents

>       number = read numberString

>       newTodoItems = unlines $ delete (todoTasks !! number) todoTasks