Читаем Учебник по Haskell полностью

data Move = Up | Down | Left | Right

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

Game будет содержать текущее положение пустой клетки и положение фишек:

data Game = Game {

emptyField

:: Pos,

gameBoard

:: Board }

Вот и все типы для описания игры. Сохраним их в модуле Game. Теперь подумаем о типах для диалога

с пользователем. В этом модуле наверняка будет много функций с типом IO, потому что в нём происходит

взаимодействие с игроком. Но, что является каркасом для диалога?

Если мы хотим с кем-нибудь общаться, необходимо чтобы у нас был с собеседником общий язык, он и

будет каркасом для диалога. Вспомним, что мы ожидаем от пользователя. Пользователь может:

• Сделать ход

• Начать новую игру

• Выйти из игры

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

показываем ему новую перемешанную позицию, давайте у нас будет разная степень перемешанности фи-

гур. При перемешивании мы стартуем из победного положения и начинаем случайным образом делать хо-

ды. Чем больше ходов мы сделаем тем сложнее будет собрать игру. Поэтому пользователь будет указывать

число шагов для перемешивания при запросе новой игры. Если пользователь попросит закончить игру мы

попрощаемся и выйдем из игры.

На основе этих рассуждений вырисовывается следующий тип для сообщений:

data Query = Quit | NewGame Int | Play Move

Значение типа Query (запрос) может быть константа Quit (выход), запрос новой игры NewGame с числом,

которое указывает на сложность новой игры, также игрок может просто сделать ход Play Move.

А каков формат наших ответов? Все наши ответы на самом деле будут вызовами функции putStrLn мы

будем отвечать пользователю изменениями экрана. Поэтому у нас нет специального типа для ответов. Итак

у нас есть каркас, который можно начинать покрывать значениями. На этом этапе у нас есть два модуля. Это

модуль Loop:

module Loop where

import Game

data Query = Quit | NewGame Int | Play Move

202 | Глава 13: Поиграем

И модуль Game:

module Game where

import Data.Array

data Move = Up | Down | Left | Right

deriving (Enum)

type Label = Int

type Pos = (Int, Int)

type Board = Array Pos Label

data Game = Game {

emptyField

:: Pos,

gameBoard

:: Board }

Ленивое программирование

Мы уже знаем как происходят ленивые вычисления. Мы принимаем выражение и начинаем очищать его

от синонимов от корня к листьям или сверху вниз. Оказывается таким способом можно писать программы.

Более того в функциональном программировании это очень распространённый подход. Мы начинаем со

спецификации задачи (неформального описания) и потихоньку вытягиваем из него выражения языка Haskell.

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

напишем верхнюю функцию, мы перейдём к подвыражениям. И так мы будем спускаться пока не напишем

всю программу.

Кажется, что такой подход очень не надёжен. Ведь мы сможем запустить программу только когда напи-

шем её целиком. На каждом промежуточном шаге у нас есть неопределённые подвыражения. Получается,

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

Оказывается, что в Haskell есть решение этой проблемы. Нам поможет значение undefined. Мы будем

писать только тип функции (и мысленно будем говорить, пусть она делает то-то), а вместо определения

будем писать undefined. При этом конечно мы не сможем выполнять программу, вычислитель подорвётся

на первом же значении, но мы сможем узнать осмысленна ли наша программа с точки зрения компилятора,

проходит ли она проверку типов. В Haskell это большой плюс. Если программа прошла проверку типов, то

скорее всего она будет работать.

Такой подход написания программ называется написанием сверху вниз. Мы начинаем с самой верхней

функции и потихоньку вычищаем все undefined. Если вспомнить ленивые вычисления, то там роль undefined

выполняли отложенные вычисления.

В чём преимущества такого подхода? Посмотрим на дерево (рис. ?? ). Если мы идём сверху вниз, то в

самом начале у нас лишь одна задача, потом их становится всё больше и больше. Они дробятся, но источ-

ник у них один. Мы всегда знаем, что нам нужно чтобы закончить нашу задачу. Написать это, это и это

подвыражение. Беда только в том, что это подвыражение содержит ещё больше подвыражений. Но сложные

подвыражения мы можем оставить на потом и заняться другими. А потом, когда мы их доделаем может вдруг

оказаться, что это сложное выражение нам и не нужно.

Рис. 13.2: Дерево задач

Стратегия написания программ | 203

Если же мы начинаем идти из листьев, то у нас много отправных точек, которые должны сойтись в одной

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных