44
Введение в функциональное программирование на примере языка ML Андрей Голованов, ФогСофт IT-Десант, 18.04.2013

десант презентация

  • Upload
    -

  • View
    97

  • Download
    0

Embed Size (px)

Citation preview

Введение в функциональное программирование на

примере языка ML

Андрей Голованов, ФогСофтIT-Десант, 18.04.2013

Read – Evaluate – Print - Loop В Emacs используется интерпретатор

NJ/SML Статическая и динамическая среда

выполнения Рестарт для зачистки данных в среде

Среда исполнения REPL

val x = e; Синтаксис:

◦ Ключевые слова val = ;

◦ Переменная x◦ Выражение e

Поддерживаются вложенные выражения

val z = (x + y) + (y + 2);

Объявление переменных и выражения

Синтаксис (как записывается) Правила проверки типов

◦ Определение типа или ошибка◦ Примеры типов: int bool unit

Правила вычисления выражения (применяются после успешной проверки типа)◦ Возвращается значение или exception или

бесконечный цикл Демо...

Правила разбора выражений

val a = 1val b = a (* b присваивается 1 *)val a = 2

Не важно что будет дальше со значением a

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

«Затенение» переменных

Синтаксис:◦ e1 + e2 где e1 и e2 это выражения

Проверка типа:◦ Если e1 и e2 имеют тип int,

то e1 + e2 тоже будет иметь тип int Вычисление выражения:

◦ Если e1 вычисляется в v1 и e2 вычисляется в v2,то e1 + e2 рассчитывается как сложение v1 и v2.

Операция сложения

Значение – это выражение, которое не требует вычислений◦ 8+9 - это не значение

Любое значение – это выражение Не все выражения являются значениями Каждое значение «вычисляется в само в

себя» без • Примеры:

◦ 34, 17, 42 имеет тип int◦ true, false имеет тип bool◦ () имеет тип unit

Значение

Синтаксис: (e1, e2, … en) Проверка типов: если e1 – имеет тип

t1, … en – tn, то выражение имеет тип t1 *…* tn

Вычисление: e1 – v1, … en – vn, то результат (v1, … , vn)

Создание кортежа

Синтаксис: #1 e, #2 e, … Проверка типов: если e имеет тип t1*…

*tn, то #1 e имеет тип t1, … Вычисление: возвращается

соответствующий элемент кортежа

Допустимы вложенные кортежиval x1 = ((1,2), (3, (4,4)))

Доступ к элементам кортежа

Построение списков◦ [] – пустой список◦ [v1, v2, …, vN] – список◦ e1::e2 – добавление элемента e1 в список e2◦ e1@e2 – слияние списков e1 и e2

Проверка типов◦ Список содержит элементы одного типа.

Пример int list, bool list, int list list Вспомогательные функции

◦ null e, hd e, tl e, length e …

Списки

В сравнении с методом из ООП языков (Java, C#)◦ Нет ключевого слова this◦ Нет return инструкции◦ Часто в ФЯ применяются рекурсивные вызовы,

например для обхода элементов коллекции

Функции особенности

Синтаксис: fun x0 (x1 : t1, … , xn : tn) = e

Вычисление: функция – это значение! Добавляется x0 в динамическую среду

выполнения Проверка типов: значение функции

определяется автоматически через выведение типов

Объявляется переменная x0: (t1*t2…*tn)->t

Объявление функции

Синтаксис: e0 (e1, …, en) Проверка типов:

– e0 имеет тип (t1 * … * tn) -> t – e1 - t1, …, en - tn e0 (e1, … , en) имеет тип t Вычисляется e0 для fun x0 (x1 : t1, … , xn :

tn) = e1. Вычисляются значения аргументов v1, …, vn2. Результат вычисления e. Динамическая среда

расширена значениями x1 : v1, …, xn : vn, а также есть x0 – для рекурсивных вызовов

Вызов функции

Демонстрация работы со списками

Синтаксис◦ Let b1 b2 … bn in e end

bi – это объявление переменной, может присваиваться выражение, объявляться функция

Проверка типов◦ Тип всего выражения определяется типом e

Область видимости (scope) Реиспользование кода (уменьшение багов,

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

Выражение let

Рекурсивно заданная функция в своем определении содержит себя

Рекурсия заменяет циклы в языке ML Хвостовая рекурсия – дешевый вызов

рекурсии (пример расчета факториала с простой и хвостовой рекурсией)◦ Применение переменной аккумулятора

Рекурсия

t option – тип для любого типа t Типы options

◦NONE имеет тип ‘a option

◦SOME e имеет тип t option, если e имеет тип t

Работа с options◦isSome тип ‘a option -> bool (false если NONE)

◦valOf тип ‘a option -> ‘a (исключение, если NONE)

Options

Не возможно выполнять операцию присвоения к переменным, частям кортежей, элементам списка

Aliasing – доступ к одному и тому же объекту, используя разные переменные.

Имея 2 функции sort_pair1 и sort_pair2, не возможно отличить возвращается ли копия кортежа или alias, в случае выполнения условия if

Неизменяемость переменных (no mutation)

fun sort_pair1 (pair : int * int) =if #1 pair < #2 pairthen pairelse (#2 pair, #1 pair)

fun sort_pair2 (pair : int * int) =if #1 pair < #2 pairthen (#1 pair, #2 pair)else (#2 pair, #1 pair)

Неизменяемость переменных (no mutation) 2

Каковы преимущества?◦ Нет возможности отличить используется ли alias

для объекта или его копия◦ Нет необходимости думать об использовании

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

возможности изменения передаваемого объекта Эта особенность применяется в

параллельных вычислениях Пример из Java. В Java поддерживается

изменение значения созданных переменных

Неизменяемость переменных (no mutation) 3

Контейнер с именованными полями Синтаксис: {f1=e1, … , fn=en}, доступ

к полю #f1 {record}, f1 – имя поля. Кортежи – это синтаксический сахар для

записей вида {1=e1, 2=e2, …, n=en}.Кортеж (e1, e2, … en), доступ #1 (tuple).

Records (записи)

Разобрали объявление переменных, функций

Примерdatatype mytype = TwoInts of int * int

| Str of string| Pizza

создали новый тип mytype. Тип имеет 3 конструктора TwoInts, Str и Pizza

Создаем конструкторы, которые производят значения нового типа

Объявление datatype

Для определения какой конструктор использован для данного экземпляра типа используются case выражения

Демо с арифметическими выражениями

Работа со значениями datatype

Pattern-matching (англ.) Используется при объявлении переменной

вместо указания имени переменнойval p = e

Используется при объявлении функцииfun f p = e

Каждая функция принимает только один аргумент

Пример с суммированием элементов кортежа

Сопоставление шаблонов

Можно указать в конструкторе datatype использование любого типа

демо с option и бинарным деревом, суммирование узлов и листьев

Полиморфизм datatype

Объявление: exception <name> of t Вызов: raise <name> <значение> Обработка: e1 handle <name>

<параметры> => e2

Исключения

Функции первого класса – могут использоваться как значения.

Функции высшего порядка - могут принимать другие функции в качестве параметра.

Пример f(f(f...f(x))) n раз (n_times) Разбор типа: fn : ('a -> 'a) * int * 'a -> 'a

Функции первого классаФункции высшего порядка

У анонимной функции нет имени, поэтому её нельзя вызывать рекурсивно

fn args => e Пример, double_n_times

Анонимные функции

Область видимости (англ. scope) – это контекст выполнения программы, где по имени можно обращаться к переменным или функциям.

Область видимости в блоке, в функции, в let-выражении, глобальный, лексический

Lexical scope. Не важно где вызывают функцию, важно где её объявили

Область видимости функции

Значение функции состоит из двух частей:◦ Код функции◦ Среда, которая была на момент определения

функции Эта пара значений называет замыканием

функции Доступ к этим свойствам значения функции

невозможен в коде При вызове функции вычисляется код в

рамках среды (которая дополняется аргументами функции)

Пример работы lexical scope.

Closure (замыкание)

Тело функции не вычисляется пока функция не будет вызвана

Тело функции вычисляется каждый раз, когда функция вызывается

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

Вычисление выражений и функций

Основные операции со списками filter, map, fold: f(f(f(acc, x1), x2), x3)

Демо с реализацией и использованием операций.

Основные операции со списками

Идиома – это элементарная конструкция типичная для одного или нескольких языков программирования в нашем случае для функциональных языков

Комбинирование функций (композиция) Currying Callback – подпись на события и

обратный вызов функций.

Идиомы в языке ML

SML использует жадную стратегию для вычислений

fun f(x:int):bool = true;fun arg () : int = 3;f(arg()) (* вызовет метод arg, хотя параметр x не используется *) Отложенные вычисления реализуются с

помощью обертки выражения анонимной функцией (thunk).

Жадное и ленивое вычисление

Статическая типизация – контроль за типами при компиляции до запуска программы (Pascal, C++, Java, C#)

Динамическая типизация – контроль типов во время выполнения программы (PHP, Python, Ruby, Perl, Javascript)

ML – статически типизированный ML – язык с неявным определением

типов. Применяется выведение типов

Статическая и динамическая типизация

Выведение типов – процесс определения типов выражений, переменных, который приведет к успешной проверке типов.

Задача выведения типов◦ Установить типы переменных в коде.◦ Удостовериться, что все выражения проходят

проверку типов.

Выведение типов

Неизменяемость значений переменных Использование функций в роли

аргумента Рекурсивные типы данных Использование рекурсии в функции для

обхода элементов списка Использование сопоставления шаблонов Ленивая инициализация

Особенности функциональных языков

Функции первого порядка, closures в C#, Java, Javascript

Анонимные функции в C#, Javascript LINQ в C# Callback в C#, Javascript Полиморфизм типов (generics) Неявная типизация, выведение типов в

C# и Javascript

Применение концепций ФЯ в ЯП

Типы и операции, матрица Разрешение задачи на ООЯП через

выделение типов и интерфейса Решение на ФЯП через определение

datatype и выделения операций с перечислением пар и pattern-matching’ом

Решение одной задачи на ФЯП и ООЯП

eval toString hasZero

Int

Add

Negate

Формулировка задачи

• В ФЯП декомпозиция по операциям• В ООП декомпозиция по

сущностям, выполняющим действия

задачи оптимизации, генетическое программировние, сложные доказательства эвристические задачи (например,

шахматы) современные языки программирования

включают в себя различные парадигмы программирования (multi-paradigm) в том числе многие идиомы из ФЯ (например, C#, Javascript).

Область применения ФЯ

Списки – это тоже datatypes Вложенные шаблоны, пример zip3,

nondecreasing, multsign sgn = P | N | Z Синонимы типов Модули и сигнатуры

Что осталось за кадром

Описание библиотечных типов языка SMLhttp://www.standardml.org/Basis/overview.html

Ссылки

Спасибо за внимание!