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

Список дел

Воспользуемся функцией >appendFile на примере написания программы, которая добавляет в текстовый файл, содержащий список наших дел, новое задание. Допустим, у нас уже есть такой файл с названием todo.txt, и каждая его строка соответствует одному заданию.

Наша программа будет читать из стандартного потока ввода одну строку и добавлять её в конец файла todo.txt:

>import System.IO


>main = do

>   todoItem <– getLine

>   appendFile "todo.txt" (todoItem ++ "\n")

Обратите внимание на добавление символа конца строки вручную, функция >getLine возвращает строку без него.

Сохраните этот файл с именем appendtodo.hs, скомпилируйте его и несколько раз запустите.

>$ ./appendtodo

>Погладить посуду

>$ ./appendtodo

>Помыть собаку

>$ ./appendtodo

>Вынуть салат из печи

>$ cat todo.txt

>Погладить посуду

>Помыть собаку

>Вынуть салат из печи

ПРИМЕЧАНИЕ. Программа >cat в Unix-подобных системах используется для вывода содержимого текстового файла на терминал. В Windows можно воспользоваться командой >type или посмотреть содержимое файла в любом текстовом редакторе.

Удаление заданий

Мы уже написали программу, которая добавляет новый элемент к списку заданий в файл todo.txt; теперь напишем программу для удаления элемента. Мы применим несколько новых функций из модуля >System.Directory и одну новую функцию из модуля >System.IO; их работа будет объяснена позднее.

>import System.IO

>import System.Directory

>import Data.List


>main = do

>   contents <– readFile "todo.txt"

>   let todoTasks = lines contents

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

>                               [0..] todoTasks

>   putStrLn "Ваши задания:"

>   mapM_ putStrLn numberedTasks

>   putStrLn "Что вы хотите удалить?"

>   numberString <– getLine

>   let number = read numberString

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

>   (tempName, tempHandle) <– openTempFile "." "temp"

>   hPutStr tempHandle newTodoItems

>   hClose tempHandle

>   removeFile "todo.txt"

>   renameFile tempName "todo.txt"

Сначала мы читаем содержимое файла todo.txt и связываем его с именем contents. Затем разбиваем всё содержимое на список строк. Список >todoTasks выглядит примерно так:

>["Погладить посуду", "Помыть собаку", "Вынуть салат из печи"]

Далее соединяем числа, начиная с >0, и элементы списка дел с помощью функции, которая берёт число (скажем, >3) и строку (например, >"привет") и возвращает новую строку (>"3 – привет"). Вот примерный вид списка >numberedTasks:

>["0 - Погладить посуду", "1 - Помыть собаку", "2 - Вынуть салат из печи"]

Затем с помощью вызова >mapM_ putStrLn numberedTasks