Методические указания

Цель практического задания — разработка законченного приложения или программной библиотеки на языке программирования Haskell.

Групповая работа

Каждое задание может быть выполнено как в одиночку, так и группой в несколько человек (максимальное количество человек в группе зависит от задания).

В каждом задании выделена базовая часть. Все участники должны разбираться в реализации базовой части и быть в состоянии воспроизвести её.

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

Для эффективной работы (в том числе в одиночку) предлагается:

Правила оформления исходного кода

Программирование — это в равной мере искусство и ремесло. И, как известно любому художнику, ограничения расширяют, а не подавляют творческие способности.

Правила оформления исходного кода:

Средства разработки

Stack

Для разработки проекта рекомендуется использовать Stack.

Stack может установить нужную версию компилятора и необходимых библиотек. Для установки компилятора необходимо запустить команду stack setup.

Для установки зависимостей Stack использует Stackage — стабильный репозиторий пакетов. Для выполнения практического задания рекомендуется использовать последний доступный LTS Haskell.

Для сборки проекта используйте команду stack build или stack test.

Для запуска интерпретатора GHCi с автоматической загрузкой модулей проекта используйте команду stack ghci.

Для запуска исполняемой программы (например, графического интерфейса) используйте команду stack exec <имя программы>.

Для автоматической сборки документации проекта используйте команду stack haddock.

Haddock

По возможности, используйте используйте разметку Haddock при написании комментариев в коде. Таким образом вы можете легко получить полноценную документацию кода вашего проекта. Вы можете локально собрать Haddock документацию, используя команду stack haddock.

Вам и вашей команде будет проще разобраться в проекте, если он будет хорошо документирован. Кроме того, навык написания хорошей документации не раз может пригодиться вам за пределами данного курса.

Рекомендации по оформлению задания

Каждое практическое задание можно реализовать множеством способов с различными наборами возможностей. Для того, чтобы другим людям (в том числе соучастникам и преподавателям) было проще разобраться в законченном проекте, рекомендуется:

Рекомендации по выбору библиотек

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

Синтаксический разбор

Для синтаксического разбора рекомендуется использовать комбинаторные библиотеки — например, Parsec или attoparsec. Parsec предоставляет более выразительные средства и лучше подходит для разбора исходного кода и конфигурационных файлов. attoparsec предлагает более простой интерфейс и меньше возможностей, но на несколько порядков лучше по производительности и подходит для разбора сетевых протоколов, логов, бинарных данных.

Генерация кода

Для генерации объектного кода проще всего использовать существующий низкоуровневый язык программирования, из которого уже можно легко получить объектный код. К таким языкам относятся C, C–– и язык LLVM. Последний часто используется в компиляторах, поскольку специально создан для этой цели.

Генерация кода для LLVM на Haskell реализуется при помощи библиотеки llvm-general.

Графический интерфейс

Библиотека gloss предоставляет простой и удобный интерфейс для работы с векторной 2D графикой. Для игр рекомендуется использование модулей Graphics.Gloss.Interface.Pure.Game или Graphics.Gloss.Interface.IO.Game. Для моделирования можно использовать модули Graphics.Gloss.Interface.Pure.Simulate или Graphics.Gloss.Interface.IO.Simulate.

Для игр также стоит использовать библиотеку gloss-game, которая предоставляет несколько удобных функций для работы со сценами.

Клиент-серверная архитектура

Для большинства практических заданий в качестве протокола общения между клиентом и сервером можно использовать HTTP. При реализации HTTP сервера рекомендуется использовать архитектуру REST.

Существует множество web-фреймворков для реализации серверной части. Для выполнения практических заданий рекомендуется использовать использовать один из следующих:

Для более тесной связи клиента и сервера рекомендуется использовать веб-сокеты. Соответствующая библиотека — websockets.

Для передачи данных по сети рекомендуется использовать сериализацию/десериализацию данных. В случае HTTP предлагается использовать формат JSON (используя библиотеку aeson). В случае веб-сокетов — бинарное представление (используя библиотеку binary).

Многопоточность

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

Для использования общей памяти между потоками одного приложения в Haskell используется программная транзакционная память. Соответствующая библиотека stm входит в список стандартных пакетов. В практических заданиях достаточно использования TVar и, возможно, TChan.

Для ознакомления с программной транзакционной памятью, рекомендуется прочтение статьи Software Transactional Memory.

База данных

Для работы с базой данных рекомендуется использовать библиотеку persistent. Эта библиотека предоставляет интерфейс, не зависящий от конкретной используемой СУБД и поддерживает как минимум PostgreSQL, SQLite, MySQL and MongoDB. Для сложных запросов (например, по нескольким таблицам) предлагается использовать библиотеку esqueleto, которая работает поверх библиотеки persistent.