100
λ

Functional Programing

Embed Size (px)

Citation preview

Page 1: Functional Programing

λ

Page 2: Functional Programing

ФП появилось раньше ООП и структурного программированияLISP 1958

Закон Мура 1965

Simula 1967

Структурное программирование 1970

ML 1973

С++ 1983

Ocaml 1985

Erlang 1987

Haskell 1990

Scala 2003

F# 2005

Clojure 2007

Elm 2012

More than Moore 2014

Page 3: Functional Programing

Но не получило распространения в индустрии из-за дороговизны памяти на заре computer science, хотя и нашло свое место в научных кругах

Page 4: Functional Programing

Интерес вернулся в последние 5 лет• Закон Мура «выдыхается»• Популярность облачных

решений растет• Big Data, машинное обучение,

боты, когнитивные сервисы

Page 5: Functional Programing

LISP• Появился в 1958 году• Создатель Лиспа Джон Маккарти занимался исследованиями в

области искусственного интеллекта (в дальнейшем ИИ) и созданный им язык по сию пору является одним из основных средств моделирования различных аспектов ИИ• Это один из старейших (наряду с Фортраном и Коболом)

используемых по сей день высокоуровневых языков программирования• Основой архитектуры его является лямбда-исчисление• Интерпретатор Лиспа, написанный на Лиспе, занимает 15 строк

Page 6: Functional Programing

Что не так с состоянием?• Locking, Memory Bandwidth• How To Reproduce / Debug• Race Conditions• Side Effects• Не возможно доказать корректность программы

Page 7: Functional Programing

Чему равен y?var x = 2;DoSomething(x);

// чему равен y?var y = x - 1;

Page 8: Functional Programing

Ответ

-1

Page 9: Functional Programing

Это JavaScript

function DoSomething (foo) { x = false }

var x = 2;DoSomething(x);var y = x - 1;

Page 10: Functional Programing

Функциональное программиирование• Раздел дискретной математики

и парадигма программирования, в которой процесс вычисления трактуется как вычисление значений функций в математическом понимании последних• Понимание функции отличается

от функции как подпрограммы в процедурном программировании

Page 11: Functional Programing

Функция –Соответствие между элементами двух множеств, установленное по такому правилу, что каждому элементу одного множества ставится в соответствие некоторый элемент из другого множества.

Page 12: Functional Programing

Принцип разделения интерфейсаПринцип разделения интерфейсов говорит о том, что слишком «толстые» интерфейсы необходимо разделять на более маленькие и специфические, чтобы клиенты маленьких

public interface IMessyCalc{ float Add(float a, float b); Rocket LaunchRocket(); // WAT?}

Page 13: Functional Programing

Принцип разделения интерфейсаpublic interface ICalc{ float Add(float a, float b);}

public interface IRocketLauncher{ Rocket LaunchRocket(); // ok}

Page 14: Functional Programing

ICalc прощеlet add x y = x + y; // float -> float -> float

Page 15: Functional Programing

Функции и вывод типовlet add1 x = x + 1 // int -> intlet add2 x = x + 2 // int -> intlet add3C = add1 >> add2 //композицияlet add3P x = x |> add1 |> add2 // pipe-операторlet toString x = x.ToString() // 'a -> string

Page 16: Functional Programing

Аналогия с конвеерной лентой

Page 17: Functional Programing

Композиция

Page 18: Functional Programing

Композиция

Page 19: Functional Programing

Каррирование и частичное применениеlet printTwoParameters x y = printfn "x=%i y=%i" x y

//explicitly curried versionlet printTwoParametersC x = // only one parameter! let subFunction y = printfn "x=%i y=%i" x y // new function with one param subFunction

let add x y = x + ylet add1P = add 1let v = add1P 2

let result = [1..10] |> List.map (fun i -> i+1) |> List.filter (fun i -> i>5)

Page 20: Functional Programing

Изменяемые данные (не тру)let mutable mut = 5mut <- 6

Page 21: Functional Programing

React/Redux Demo

Page 22: Functional Programing

λ-исчисление• Формальная система, разработанная американским математиком

Алонзо Чёрчем, для формализации и анализа понятия вычислимости• Строится на простых двух операциях: аппликации и абстракции• Определены фундаментальные понятия α-эквивалентностью и β-

редукции• Многие функциональные языки можно рассматривать как

"надстройку" над ними

Page 23: Functional Programing

λ-исчисление• Нет циклов• Нет переменных• Нет операции присвоения• Нет изменяемого состояния• Нет условных переходов и циклов• Нет «обычной» рекурсии• Обладает свойством полноты по Тьюрингу

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

Page 24: Functional Programing

Теорема о неподвижной точке• И в λ-исчислении, и в комбинаторной логике для каждого терма X

существует по крайней мере один терм P такой, что XP = P. И более того, существует комбинатор Y такой, что YX = X(YX)• Комбинатор неподвижной точки преобразует нерекурсивную

функцию, вычисляющую один шаг рекурсии, в рекурсивную• Y = λf.(λx.f(xx))(λx.f(xx))• Z = λf.(λx.f(λy.xxy))(λx.f(λy.xxy))• https://habrahabr.ru/post/79713/

Page 25: Functional Programing

α-эквивалентность• λx.x и λy.y альфа-эквивалентные лямбда-термы и оба

представляют одну и ту же функцию (функцию тождества). • Термы x и y не альфа-эквивалентны, так как они не находятся в

лямбда абстракции

Page 26: Functional Programing

β-редукция•(λx.2 * x + 1)3 -> 7

Page 27: Functional Programing

Структурирование программExpressions VS StatementsExpression<Func<int, string>> expr = x => { return x.ToString(); };

CS0834 A lambda expression with a statement body cannot be converted to an expression tree

Page 28: Functional Programing

Statementvar str = "test";var i = 1;if (flag){ str += i;}else{ i++;}

Page 29: Functional Programing

Expressionvar fiveOrSix = Math.Cos(1) > 0 ? 5 : 6;

Page 30: Functional Programing

FixedExpression<Func<int, string>> expr = x => x.ToString(); // ok

Page 31: Functional Programing

Что возвращает функция?function DoSomething (foo) { if (foo > 5) return 2; throw "Error";}

var x = 2;DoSomething(x);var y = x - 1;

Page 32: Functional Programing

Exception Handling Considered Harmful•Hidden Control Flow & Corrupt State•Mismatch With Parallel Programming• Exceptional Exceptions• Exceptions only really work reliably when nobody

catches them

Page 33: Functional Programing

do { using (var lifetimeScope = _container.BeginLifetimeScope()) { var billingService = lifetimeScope.Resolve<BillingService>(); try { int activityCount = billingService.ProcessNotRatedActivities(); if (activityCount > 0) { Logger.Instance.Info($"Handled {activityCount} pending rated activities"); } } catch (Exception exception) { Logger.Instance.Error(exception, CultureInfo.CurrentCulture,

"An error occured while handling pending rated activities"); } } } while (!cancellationToken.WaitHandle.WaitOne(_pollingInterval));

Page 34: Functional Programing

Ограничения императивного стиля

Page 35: Functional Programing

Cross-cutting concerns

Page 36: Functional Programing

Convert exceptions into Failures

Page 37: Functional Programing
Page 38: Functional Programing
Page 39: Functional Programing

Алгебраические типы данныхtype Option<'T> = | Some of 'T | None

type Season = Autumn | Winter | Spring | Summer

type Profile = { FirstName: string LastName: string}

Page 40: Functional Programing

Pattern Matchinglet printSomeOrNone x = match x with | Some(y) -> printfn "some: %A" y | None -> printfn "none"

| _ -> printfn "Never hit" // only use if you have to

Page 41: Functional Programing

Организация приложения в функциональном стиле

Page 42: Functional Programing
Page 43: Functional Programing
Page 44: Functional Programing
Page 45: Functional Programing
Page 46: Functional Programing
Page 47: Functional Programing
Page 48: Functional Programing
Page 49: Functional Programing
Page 50: Functional Programing
Page 51: Functional Programing
Page 52: Functional Programing
Page 53: Functional Programing
Page 54: Functional Programing

Монада – это просто моноид в категории эндофункторов• Если не затрагивать тему гомоморфизмов• В чем проблема?

Page 55: Functional Programing

Какие милые котята

Page 56: Functional Programing

Ой, какие щеночки

Page 57: Functional Programing

Уиии, лошадки

Page 58: Functional Programing

Определение порядковых чисел по фон Нейману• Множество S является ординалом тогда и только тогда, когда оно

строго вполне упорядочено отношением «принадлежать» и каждый элемент S одновременно является его подмножеством• Любой ординал есть вполне упорядоченное множество,

состоящее из всех ординалов, меньших его

Page 59: Functional Programing
Page 60: Functional Programing

Основы теории категорий• В программах, использующих операционную семантику, очень трудно

что-то доказать. Чтобы показать некое свойство программы вы, по сути, должны «запустить ее» через идеализированный интерпретатор• Но есть и альтернатива. Она называется денотационной семантикой и

основана на математике. В денотационной семантике для каждой языковой конструкции описана математичесая интерпретация• По сравнению с теоремами, которые доказывают профессиональные

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

Page 61: Functional Programing

Какова математическая модель для чтения символа с клавиатуры, или отправки пакета по сети?• Долгое время это был бы неловкий вопрос, ведущий к довольно

запутанным объяснениям. Казалось, денотационная семантика не подходит для значительного числа важных задач, которые необходимы для написания полезных программ, и которые могут быть легко решаемы операционной семантикой• Прорыв произошел из теории категорий. Евгенио Моджи

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

Page 62: Functional Programing

Чистая функция• Является детерминированной• Не обладает побочными эффектами• В Haskell все функции чистые, поэтому без монады IO нельзя

написать hello world

Page 63: Functional Programing

Категория

Page 64: Functional Programing

Warning Math ahead

Page 65: Functional Programing

Моноид – это категория• 1 + 2 = 3• 1 + (2 + 3) = (1 + 2) + 3• 1 + 0 = 1• 0 + 1 = 1

Page 66: Functional Programing

Строки – тоже моноид• "Foo" + "Bar" = "FooBar"• "Foo" + ("Bar" + "Baz") = ("Foo" + "Bar") + "Baz"• "Foo" + "" = "Foo«• "" + "Foo" = "Foo"

Page 67: Functional Programing

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

Page 68: Functional Programing

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

Page 69: Functional Programing

Map (fmap, lift, Select, <$>, <!>)1. (a->b) -> M<a> -> M<b>2. fmap id = id3. fmap (g >> f) = (fmap g) >> (fmap f)

Page 70: Functional Programing
Page 71: Functional Programing
Page 72: Functional Programing
Page 73: Functional Programing

Return ( pure, unit, yield, point)• A -> M<A>

Page 74: Functional Programing

Apply <*>• M<(a->b)> -> M<a> -> M<b>• Аппликативные функторы применяют упакованную функцию к

упакованному же значению:• Используя apply и return можно сконструировать map

Page 75: Functional Programing
Page 76: Functional Programing

Bind (flatMap, andThen, SelectMany >>=)• (a -> M<b>) -> M<a> -> M<b>

Page 77: Functional Programing

>>=

Page 78: Functional Programing
Page 79: Functional Programing

Maybe• Является функтором, аппликативным функтором и монадой

одновременно

Page 80: Functional Programing

Все вместе• функтор: вы применяете функцию к упакованному значению,

используя fmap или <$>• аппликативный функтор: вы применяете упакованную функцию к

упакованному значению, используя <*> или liftA• монада: вы применяете функцию, возвращающую упакованное

значение, к упакованному значению, используя >>= или liftM

Page 81: Functional Programing
Page 82: Functional Programing
Page 83: Functional Programing
Page 84: Functional Programing
Page 85: Functional Programing
Page 86: Functional Programing
Page 87: Functional Programing

Either Control Flow public static ActionResult ViewOrError<TIn, TOut>(

this IQueryController<TIn,TOut> controller, TIn spec) where TIn : class, new() where TOut : class => spec.ThisOrDefault() .ToWorkflow( x => controller.ModelState.IsValid, x => (OrderFailure?)OrderFailure.ArgumentInvalidState) .Then(x => controller.Query.Ask(x)) .Then(x => x != null, controller.View, x => OrderFailure.ObjectNotFound) .Finish(x => x, x => x.ToActionResult());

Page 88: Functional Programing

Императивный аналог protected ActionResult ViewOrErrorImperative<TIn, TOut>(IQuery<TIn, TOut> query, TIn spec) where TIn : class, new() where TOut : class {

if (spec == null) { spec = new TIn(); }

if (ModelState.IsValid) { var data = query.Ask(spec); if (data != null) { return View(data); }

return new HttpNotFoundResult(); }

return new HttpStatusCodeResult(HttpStatusCode.BadRequest); }

Page 89: Functional Programing

Монады• LINQ• Async/Await• Map/Reduce• Lazy<T>• Nullable<T>• IEnumerable<T>• Task<T>

Page 90: Functional Programing

SelectMany public static Maybe<int> Add(this Maybe<int> m, Maybe<int> add) => from v1 in m from v2 in add select v1 + v2;

Page 91: Functional Programing

Бастион ООП содержит монады (на странице 243)

Page 92: Functional Programing

Interpreter is Free Monad

Page 93: Functional Programing

Interpreter• Expression Tree• RegEx

Page 94: Functional Programing

Другие элементы ФП, которые мы используем каждый день• Делегаты• Ad-Hoc полиморфизм• String• Замыкания• Bind• Promise

Page 95: Functional Programing

ООП VS ФП• Инкапсуляция -> Immutability• Наследование -> Композиция, Каррирование, Частичное

применение, Continuation Style• Полиморфизм -> Вывод типов, Монады

Page 96: Functional Programing

Сильные стороны• Повышение надёжности кода• Возможность формального доказательства корректности программы• Удобство организации модульного тестирования• Возможности оптимизации при компиляции• Возможности параллелизма• Лучшие возможности композиции и повторного использования кода• Значительное уменьшение количества строк кода и cyclomatic complexity• Лучшая читабельность

Page 97: Functional Programing

Недостатки• Необходимости постоянного выделения и автоматического

освобождения памяти• Нестрогая модель вычислений приводит к непредсказуемому порядку

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

важных эмпиративных алгоритмов (например, quicksort)• Нехватка специалистов на рынке труда• В Haskell ввод/вывод реализован с помощью не тривиальных

абстракций – монад

Page 98: Functional Programing

Сколько раз в день ваша бабушка пользуется ПО?• Ни одного• Один раз• От двух до пяти• Да постоянно!

Page 99: Functional Programing

Сколько раз в день ваша бабушка пользуется ПО?• Начисление пенсии• Оплата товаров в магазине• Социальные льготы• Медицинское страхование• ...

Page 100: Functional Programing

Список использованных материалов• http://fsharpforfunandprofit.com/• https://habrahabr.ru/post/79713/• https://habrahabr.ru/post/183150/• https://habrahabr.ru/post/245797/• https://ru.wikipedia.org/• https://ericlippert.com/2013/02/21/monads-part-one/• http://blog.ploeh.dk/2016/04/11/async-as-surrogate-io/• https://www.youtube.com/watch?v=ecIWPzGEbFc