52700.fb2 Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 150

Учебник по Haskell - читать онлайн бесплатно полную версию книги . Страница 150

надстроены над C (например физический движок Hipmunk).

8.7 Краткое содержание

Наконец-то мы научились писать программы! Программы, которые можно исполнять за пределами ин-

терпретатора. Для этого нам пришлось познакомиться с типом IO. Экземпляр класса Monad для этого типа

интерпретируется специальным образом. Он вносит упорядоченность в выполнение программы. В нашем

статическом мире описаний появляются такие понятия как “сначала”, “затем”, “до” и “после”. Но они не

смогут нанести много вреда.

Вычисление операций с побочными эффектами разбивает программу на кадры. Но это не мешает нам

писать основные функции в чистом виде, подставляя их по мере необходимости в изменчивый мир побочных

эффектов с помощью методов из классов Functor, Applicative, Monad.

Мы узнали как в Haskell обстоят дела с такими типичными задачами мира побочных эффектов как

ввод/вывод, чтение/запись файлов, генерация случайных значений, выполнение внешних программ, ини-

циализация программ с помощью флагов. Также мы узнали о том, как обрабатываются специфические для

типа IO исключения.

140 | Глава 8: IO

8.8 Упражнения

Старайтесь свести присутствие функций с побочными эффектами к минимуму. Идеальный случай, когда

тип IO встречается только в функции main. Часто программы устроены более хитрым образом и функции

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

разделить на две части: в одной живут подлинные источники побочных эффектов, такие как чтение файлов,

генерация случайных значений, а в другой – чистые функции. Старайтесь устроить программу так, чтобы

она была максимально чистой. Чистые функции гораздо проще комбинировать, понимать, изменять.

• Это упражнение даёт вам возможность почувствовать преимущества чистого кода. Вспомните функ-

цию поиска корней методом неподвижной точки (этот пример встречался в главе о ленивых вычисле-

ниях). Напишите на основе этого примера программу, которая будет распечатывать решение и после-

довательность приближений. Последовательность приближений состоит из текущего значения корня

и расстоянии между корнями.

Напишите два варианта программы, в одном вы измените алгоритм так, чтобы печать происходила

одновременно с вычислениями (не пользуясь функцией из модуля Debug.Trace). А в другом вариан-

те алгоритм останется прежним. Но теперь вместо решения найдите список первых приближений до

решения. А затем передайте его в отдельную функцию печати результатов.

В первом варианте алгоритм смешан с печатью. А во втором программа распадается на две части, часть

вычислений и часть вывода результатов на экран. Сравните два подхода.

• Напишите программу для угадывания чисел. Компьютер загадал число в заданном диапазоне и про-

сит вас угадать его. Если вы ошибаетесь он подсказывает: “холодно-горячо” или “больше-меньше”.

Программа принимает два аргумента, которые определяют диапазон возможных значений для неиз-

вестного числа.

• С помощью стандартных функций для генерации случайных чисел напишите программу, которая про-

водит состязание по игре в кости. Программа принимает аргументом суммарное число очков необходи-

мых для победы. Двое игроков бросают по очереди кости побеждает тот, кто первым наберёт заданную

сумму.

Сделайте так чтобы результаты выводились постепенно. С каждым нажатием на Enter вы подбрасы-

ваете кости (два шестигранных кубика). После каждого раунда программа выводит промежуточные

результаты.

• Напишите программу, которая принимает два аргумента: набор слов разделённых пробелами и файл.

А выводит она строки файла, в которых встречается данное слово.

Воспользуйтесь стандартными функциями из модуля Data.List

-- разбиение строки на подстроки по переносам каретки

lines :: String -> [String]

-- разбиение строки на подстроки по пробелам