
- •Оглавление
- •От автора
- •Структура
- •Пояснения и обозначения
- •Демонстрация кунг-фу
- •Теория Основные понятия и типы данных
- •Кортежи
- •Функции, операторы
- •Полиморфные типы данных
- •Чтение сигнатур типов
- •Простейшие функции и операторы
- •Арифметические функции
- •Логические функции
- •Списочные функции
- •Кортежные функции
- •Создание своих функций
- •Способ 1. Определение функции как выражения от параметров:
- •Способ 2. Несколько определений одной функции:
- •Способ 3. Определение функции через синоним:
- •Способ 4. Лямбда функция (анонимная функция):
- •Способ 5. Частичное применение функции:
- •Образцы и сопоставление с образцом
- •Синтаксический хлеб и синтаксический сахар
- •Условия и ограничения
- •Локальные определения
- •Двумерный синтаксис
- •Арифметические последовательности
- •Замыкания списков
- •Функциональное мышление
- •Рекурсия как основное средство
- •Ручная редукция выражений
- •Думаем функционально, шаг раз
- •Думаем функционально, шаг два: аккумуляторы
- •Реализация простейших списочных и прочих функций
- •Думаем функционально, шаг три: хвостовая рекурсия
- •Еще раз о рекурсии
- •Полезные хитрости языка
- •Ленивые вычисления и строгие функции
- •Бесконечные списки
- •Функция show
- •Совсем немного о классах
- •Функция read
- •Функция error
- •Побочные эффекты и функция trace
- •Функции высших порядков
- •Мотивация
- •Функция map
- •Функция filter
- •Композиция функций
- •Функция foldr
- •Функция foldl
- •Свертки: разбор полетов
- •Выявление общей функциональности
- •Стандартные функции высших порядков
- •Еще немного про строгие функции
- •Создание своих типов данных
- •Простые перечислимые типы данных
- •Контейнеры
- •О сравнении, отображении и прочих стандартных операциях
- •Параметрические типы данных
- •Сложные типы данных
- •Тип данных Maybe
- •Рекурсивные типы данных: списки
- •Рекурсивные типы данных: деревья
- •Ввод-вывод
- •Простейший ввод-вывод
- •Объяснение кухни
- •Пример программы, производящей нетривиальное преобразование текстового файла
- •Пример решения задачи: Поиск в пространстве состояний
- •Через массивы и последовательность промежуточных состояний
- •Решение для тех, кто не хочет разбираться сам
- •Через списки, лог истории и уникальную очередь
- •Решение для тех, кто не хочет разбираться сам
- •Задачник
- •Пояснения и обозначения
- •Лабораторная работа 1 Простейшие функции
- •Простейшие логические функции
- •Простейшие списочные функции
- •Лабораторная работа 2 Символьные функции
- •Простейшие кортежные функции
- •Теоретико-множественные операции
- •Сортировка
- •Арифметические последовательности
- •Генераторы списков
- •Лабораторная работа 4 Бесконечные списки
- •Ввод-вывод
- •Нетривиальные функции
- •Лабораторная работа 5 Простые числа и факторизация
- •Деревья
- •Деревья вычислений
- •Дополнительные задания для самостоятельной работы Задания с Project Euler
- •Простейший инструментарий Установка WinHugs и начало работы
- •Работа с интерпретатором WinHugs в интерактивном режиме
- •Команды интерпретатору
- •Работа с модулями
- •Список рекомендуемой литературы и электронных ресурсов
Команды интерпретатору
Каждая вводимая пользователем строка расценивается Hugs как команда интерпретатору. Если вводимая строка представляет из себя выражение, то, как было показано раньше, она рассматривается как команда интерпретатору вычислить значение этого выражения и вернуть его пользователю. Кроме выражений пользователь может использовать набор заранее определенных команд, самой главной из которых является ":?".
При вводе такой команды Hugs вернет список команд, которые могут быть использованы, все они начинаются с двоеточия.
Некоторые команды приведены ниже. Самой важной и полезной командой здесь является команда ":t", возвращающая тип функции.
:l <filenames> загрузить модули из файлов
:r перезагрузить текущий модуль
:e <filename> редактировать модуль
:e редактировать текущий модуль
<expr> вычислить значение выражения
:t <expr> вывести тип выражения
:? вывести список доступных команд
:n [pat] вывести функции с именем,
подходящим под шаблон [pat]
:q выйти из интерпретатора
Работа с модулями
Функции типа sum, (+), take и прочие, использованные в приведенных выше примерах являются стандартными и определены в стандартных модулях. В этом загружаемом по умолчанию модуле определено огромное количество полезных функций; но, разумеется, чтобы сделать что-то полезное, необходимо уметь создавать свои собственные функции. Лучше всего при этом создавать их в собственном модуле (или модулях) и загружать в Hugs. Модуль – это всего-лишь набор определений, хранимых в каком-то файле. Разумеется, в каждом модуле может храниться множество определений функций.
Например, создадим следующий модуль и сохраним его в файле fact.hs. (Модули Hugs обычно имеют расширение ".hs", а имя модуля должно совпадать с именем файла и начинаться с прописного символа.
module Fact where
fact :: Integer -> Integer
fact n = product [1..n]
Функция product, использованная здесь, является стандартной и определена в стандартном модуле; она используется для вычисления произведения всех числен из списка, так же как функция sum используется для вычисления суммы списка чисел.
Таким образом, приведенные выше строки определяют функцию, которая берет число, обозначаемое n и вычисляет его факториал. В стандартной математической записи fact n = n! определяется следующим образом:
n! = 1 * 2 * ... * (n-1) * n
Когда вы привыкнете к используемой Hugs нотации, то заметите, что определения функций в Hugs очень часто близки к неформальным математическим определениям. Еще одно часто используемое математическое определение факториала выглядит следующим образом:
f(0) = 1
f(n) = n * f(n-1)
Совершенно аналогичным образом можно было определить функцию в Hugs. Для этого добавим три строчки в конец определенного ранее модуля Fact:
f :: Integer -> Integer
f 0 = 1
f n = n * f (n-1)
Для того, чтобы можно было использовать введенные определения в среде интерпретатора, модуль необходимо загрузить. Для этого используется команда :load (или :l , потому что все команды можно сокращать до первой буквы):
Hugs> :l fact.hs
Fact>
То же самое можно было выполнить с помощью кнопки в командном окне интерпретатора, если файл находится не в каталоге программы. Заметьте, что к модулю Hugs, используемому интерпретатором, теперь добавился файл Fact.hs. Приглашение к работе теперь тоже изменилось, и оно говорит о том, что теперь мы можем использовать определенные в модуле функции:
Fact> fact 6
720
Fact> fact 6 + fact 7
5760
Fact> fact 7 `div` fact 6
7
Fact>
В одном модуле можно подключить функциональность из другого модуля. Для этого нужно написать в модуле, например:
import Char
Теперь, после того, как весь основной инструментарий готов, пора приступать к изучению собственно теории и практики функционального программирования на языке Haskell.