
- •1. Введение в декларативные языки.
- •Прозрачность по ссылкам.
- •Логическое программирование
- •Правила
- •Примеры
- •Рекурсивные определения
- •Литература
- •Синтаксис пролога.
- •Структуры
- •Предикаты
- •Семантика пролога
- •Как происходит сопоставление
- •Алгоритм Эрбрана
- •Алгоритм вычисления целей(работы пролог машины).
- •Процедурный смысл правил
- •Использование списков и
- •Использование накапливающего параметра(прием)
- •Операторная запись
- •Управление перебором
- •Алгоритмы сортировки
- •1 Пузырьковая сортировка
- •Сортировка вставками
- •Быстрая сортировка.
- •Использование предикатов, анализирующих типы или структуру термов
- •Применение подстановки к структурированному терму
- •Недетерминированное программирование
- •Метод «породить и проверить»
- •Алгоритм сортировки
- •Программирование второго порядка
- •Рассмотрим, как работать с базой данный
- •Поиск в глубину
- •Темы кр
- •Использование формальных языков
- •Недетерминированный конечный автомат
- •Ввод и вывод
- •Рассмотрим ввод вывод алфавитно – цифровых символов
- •Функциональное программирование
- •Базовый язык
- •Рекурсивное определение функций
- •Функции высших порядков
- •Отображение списков
- •Декартово произведение множеств
- •Композиция функций.
- •Бесконечные списки
- •Рассмотрим как можно исп беск списки.
- •Метод породить и проверить
- •Сети связанных процессов
- •Определение ф чисел фибоначи
- •Задача хэмминга
- •Решето Эратосфена
- •Язык типов
- •Рассмотрим алгебраические типы данных.
- •Деревья – рекурсивные типы данных
- •Сделать дерево плоским
- •Удаление элемента дерева
- •Извлечение самого правого элемента
- •Функция форматирования числа
- •Законы функциональных программ
- •Наиболее важные законы функц программ доказываются по индукции
- •Закон map через foldr
- •Закон: композиция
- •Коммутативна
- •Дистрибутивность map относительно композиции:
- •Преобразование программ
- •Пример1
- •Стратегия для композиции
- •Приведение рекурсивной формы к итеративной форме
- •Введение в лямбда исчисление
- •Синтаксис лямбда исчисления
- •Множество связанных переменных
- •Множество свободных переменных
- •Подстановка
- •Конфликт имен(захват переменных)
- •Преобразование термов
- •Вторая теорема Черча – Россера “Теорема о стандартизации”
- •Комбинатор y
- •Вычислим fact 3
- •Вычислим fact 0
- •(Рассказ про y комбинатор – сразу зачёт)
Функции высших порядков
Когда мы рассматривали базовый язык функции явл объектами первого класса, с ними можно выполнять операции. В этой главе мы рассмотрим такого рода функции.
Функции, которые получают аргументы или дают результаты функции, называются функциями высших порядков.
В функц программе таких функций большинство.
add = \x->\y->x+y
Функции высших порядков позв определять целое семейство функций.
inc = add 1
dec = add (-1)
id = add 0
Функции высших порядков позв программировать на высоком уровне абстракции.
Сходство функций
Можно найти классы функций в которых много общего
Суммирует эелементы списка :
Sum [] = 0
Sum (x:xs) = x + sum xs
// prod перемножает
Prod [] = 1
Prod (x:xs) = x*prod xs
// and строит конъюнкцию всех элементов списка
And [] = True
And (x:xs) = X && and xs
Эти функции можно обобщить.
Обнаруживается общая схема рекурсии.
Каждой функции задается некоторое начальное значение.
0, 1, и True. Это отличительный признак.
Далее эти функции отличаются выполняемой операцией. + * &&
Если эти нач компоненты обозначить переменной, то мы получим более абстрактную функцию.
fold op init [] = init
fold op init (x:xs) = X `op` fold op init xs
ф-ия op и нач значение init от шага к шагу не меняется, но тем не менее передаются.
Или более компактно (эффективно)
fold op init ys = h ys
where
h [] = init
h (x:xs) = X `op` h xs
Функция полиморфна. Её тип
fold:: (a->b->b)->b->[a]->b
Функций fold для полноты нужно две, мы можем операцию взять левоассоциативную и правоассоциативную.
Foldr op init (x1 : x2 : … xn : [])
X1 `op` (x2 `op` (…(xn `op` init)…))
Операции прим справа налево
Foldl op init (x1 : x2 : … xn : [])
(…((init `op` x1) `op` x2)…) `op`xn
Если операция оп ассоциативна то можно брать любую из 2х функций.
Иногда правильный выбор между foldr и foldl может повысить эффективность. Сцепление списков выполним…
Foldr (++) [] [x,y,z] -> x ++ (y ++ z)
Foldl (++) [] [x,y,z] -> (x ++ y) ++ z
Рассмотрим пример где можно применить fold. Для реверсирования списков.
Reverse [] = []
Reberse (x:xs) = reverse xs ++ [x]
Лучше исп накапливающий параметр:
reverse xs = rev [] xs
where rev acc [] = acc
rev acc (x:xs) = rev (x:acc) xs
локальная ф rev – если исчерпался то результат то что накоплено в акк. Если список имеет голову и хвост то мы реверсируем хвост а голову окунаем в аккумулятор.
Rev напоминает наши предыдущие функции. Можно обратиться к асбтрактной фукнции…
Очень похоже на Foldl.
reverse xs = foldl revOp [] xs
where revOp a b = b : a
вместо revOp(она на один случай) мы можем написать:
(\ a b -> b : a)
Отображение списков
map _ [] = []
map f (x:xs) = f x : map f xs
map f xs = map’ xs
where
map’ [] = []
map’ (x:xs) = f x : map’ xs
ф f не меняется, лучше исп локальную функцию.
Example:
map(+1) [1,2,3] => [2,3,4]
Декартово произведение множеств
Список всех рядов
для каждого х из xs построить пару. берем y ….
cartProd :: [a] -> [b] ->[(a,b)]
cartProd xs ys = foldr (++) []
(map
Ряд для каждого x из xs
(\x -> (map (\y->(x,y)) ys))xs)
Список должен быть плоским ( foldr (++) ).