
- •Оглавление
- •От автора
- •Структура
- •Пояснения и обозначения
- •Демонстрация кунг-фу
- •Теория Основные понятия и типы данных
- •Кортежи
- •Функции, операторы
- •Полиморфные типы данных
- •Чтение сигнатур типов
- •Простейшие функции и операторы
- •Арифметические функции
- •Логические функции
- •Списочные функции
- •Кортежные функции
- •Создание своих функций
- •Способ 1. Определение функции как выражения от параметров:
- •Способ 2. Несколько определений одной функции:
- •Способ 3. Определение функции через синоним:
- •Способ 4. Лямбда функция (анонимная функция):
- •Способ 5. Частичное применение функции:
- •Образцы и сопоставление с образцом
- •Синтаксический хлеб и синтаксический сахар
- •Условия и ограничения
- •Локальные определения
- •Двумерный синтаксис
- •Арифметические последовательности
- •Замыкания списков
- •Функциональное мышление
- •Рекурсия как основное средство
- •Ручная редукция выражений
- •Думаем функционально, шаг раз
- •Думаем функционально, шаг два: аккумуляторы
- •Реализация простейших списочных и прочих функций
- •Думаем функционально, шаг три: хвостовая рекурсия
- •Еще раз о рекурсии
- •Полезные хитрости языка
- •Ленивые вычисления и строгие функции
- •Бесконечные списки
- •Функция show
- •Совсем немного о классах
- •Функция read
- •Функция error
- •Побочные эффекты и функция trace
- •Функции высших порядков
- •Мотивация
- •Функция map
- •Функция filter
- •Композиция функций
- •Функция foldr
- •Функция foldl
- •Свертки: разбор полетов
- •Выявление общей функциональности
- •Стандартные функции высших порядков
- •Еще немного про строгие функции
- •Создание своих типов данных
- •Простые перечислимые типы данных
- •Контейнеры
- •О сравнении, отображении и прочих стандартных операциях
- •Параметрические типы данных
- •Сложные типы данных
- •Тип данных Maybe
- •Рекурсивные типы данных: списки
- •Рекурсивные типы данных: деревья
- •Ввод-вывод
- •Простейший ввод-вывод
- •Объяснение кухни
- •Пример программы, производящей нетривиальное преобразование текстового файла
- •Пример решения задачи: Поиск в пространстве состояний
- •Через массивы и последовательность промежуточных состояний
- •Решение для тех, кто не хочет разбираться сам
- •Через списки, лог истории и уникальную очередь
- •Решение для тех, кто не хочет разбираться сам
- •Задачник
- •Пояснения и обозначения
- •Лабораторная работа 1 Простейшие функции
- •Простейшие логические функции
- •Простейшие списочные функции
- •Лабораторная работа 2 Символьные функции
- •Простейшие кортежные функции
- •Теоретико-множественные операции
- •Сортировка
- •Арифметические последовательности
- •Генераторы списков
- •Лабораторная работа 4 Бесконечные списки
- •Ввод-вывод
- •Нетривиальные функции
- •Лабораторная работа 5 Простые числа и факторизация
- •Деревья
- •Деревья вычислений
- •Дополнительные задания для самостоятельной работы Задания с Project Euler
- •Простейший инструментарий Установка WinHugs и начало работы
- •Работа с интерпретатором WinHugs в интерактивном режиме
- •Команды интерпретатору
- •Работа с модулями
- •Список рекомендуемой литературы и электронных ресурсов
Нетривиальные функции
Напишите функцию intersperse :: a -> [a] -> [a], вставляющую заданный элемент между всеми элементами заданного списка. Например, intersperse ',' "abcde" == "a,b,c,d,e".
Напишите функцию explodeMy :: a -> [a] -> [[a]], разбивающую заданный список элементов на подсписки в тех местах, где встречается заданный элемент. Например, explode ',' "a,b,c,d,e" == ["a","b","c","d","e"].
Напишите функцию explodeBy :: (a -> Bool) -> [a] -> [([a],[a])], разбивающую заданный список элементов по заданному условию на кортежи из двух подсписков подряд идущих элементов. В каждом кортеже в первом подсписке содержатся подряд идущие элементы, на которых условие возвращает True, а во втором – False. Например, explodeBy (`elem` ".!?") "Something happened... Finally!" == [("Something happened","..."),(" Finally","!")].
Напишите функцию transpose :: [[a]] -> [[a]], которая берет список списков и транспонирует столбцы и строки. Например, transpose [[1,2,3],[4,5,6]] == [[1,4],[2,5],[3,6]].
Напишите функцию permutations :: [a] -> [[a]], находящую все возможные перестановки заданной последовательности. Например, permutations "abc" == ["abc","bac","cba","bca","cab","acb"].
Напишите функцию group :: Eq a => [a] -> [[a]], группирующую подряд идущие одинаковые элементы в отдельный подсписок. Например, group "Mississippi" = ["M","i","ss","i","ss","i","pp","i"].
Напишите функцию groupBy :: (a -> a -> Bool) -> [a] -> [[a]], делающую то же самое, что и group, но по задаваемой операции сравнения.
Напишите функцию inits :: [a] -> [[a]], находящую все префиксы заданного списка. Например, inits "abc" == ["","a","ab","abc"].
Напишите функцию tails :: [a] -> [[a]], находящую все суффиксы заданного списка. Например, tails "abc" == ["abc","bc","c",""].
Напишите функцию infixesMy :: [a] -> [[a]], находящую все непрерывные подсписки заданного списка. Например, infixesMy "abc" == ["","a","b","c","ab","bc","abc"].
Напишите функцию subsequences :: [a] -> [[a]], находящую все возможные подпоследовательности заданной последовательности. Например, subsequences "abc" == ["","a","b","ab","c","ac","bc","abc"].
Напишите функцию isPrefixOf :: Eq a => [a] -> [a] -> Bool, проверяющую, является ли одна строка префиксом другой.
Напишите функцию isSuffixOf :: Eq a => [a] -> [a] -> Bool, проверяющую, является ли одна строка суффиксом другой.
Напишите функцию isInfixOf :: Eq a => [a] -> [a] -> Bool, проверяющую, является ли одна строка инфиксом (подстрокой) другой.
Напишите функцию isSubsequenceOfMy :: Eq a => [a] -> [a] -> Bool, проверяющую, является ли одна строка подпоследовательностью другой.
Напишите функцию cumSumPostfixMy :: Num a => [a] -> [a], которая вычисляет кумулятивные суммы всех постфиксов списка, составляя из списка [x1,x2,…xN] список [x1+…+xN,x2+…+xN,…,x(N-1)+xN,xN]. Например, cumSumPostfixMy [1,2,2,4] == [9,8,6,4].
Напишите функцию cumSumPrefixMy :: Num a => [a] -> [a], которая вычисляет кумулятивные суммы всех префиксов списка. Например, cumSumPrefixMy [1,2,2,4] == [1,3,5,9].
Напишите функцию diffMy :: [Int] -> [Int], которая вычисляет разницы между парами подряд идущих чисел, составляя из списка [x1,x2,…xN] список [x2-x1,x3-x2,…,xN-x(N-1)]. Говорят, это называется численным дифференцированием табулированной функции. Например, diffMy [1,2,2,4] == [1,0,2]. Попробуйте использовать функцию zipWith и (-).
Дана строка вида "2*3 5 3*2 0 4*2", в которой присутствуют как отдельные числа, так и конструкции типа "N*K". Напишите функцию String -> String, строящую новую строку по заданной с помощью следующих преобразований: отдельные числа переходят в строку-результат как есть, а конструкции типа "N*K" преобразуются в строку "N N N ... N", где N повторяется K раз. Например, foo "2*3 5 3*2 0 4*2" == "2 2 2 5 3 3 0 4 4".
Напишите обратную функцию к предыдущей, используя group.
Напишите функцию [Int] -> [Int], находящую для каждого числа списка, сколько чисел имеется строго меньше него и выводящую в результирующий список на соответствующей позиции это количество. Например, foo [1,5,3,4,3] = [0,4,1,3,1].