1 / 48

Функциональное программирование

Функциональное программирование. Функциональное программирование. Симуни Михаил Лазаревич msimuni.wikidot.com/fp группа ВКонтакте “ Функциональное программирование (мат-мех 14 ) ” simuni@mail.ru. Что надо будет для зачета?. Набрать >= 20 баллов Контрольная в середине курса

Download Presentation

Функциональное программирование

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Функциональное программирование

  2. Функциональное программирование Симуни Михаил Лазаревич msimuni.wikidot.com/fp группа ВКонтакте “Функциональное программирование (мат-мех 14)” simuni@mail.ru

  3. Что надо будет для зачета? • Набрать >= 20 баллов • Контрольная в середине курса • Зачет: задачи + теор.вопросы • Больше баллов – льготы на зачете 30 – минус 1 задача40 – минус 2 задачи50 – минус 3 задачии т.д.

  4. Откуда берутся баллы Задачи на дом (примерно по 4 задачи на занятии) И еще будут дополнительные задачи посложнее MOOC ? Scala – Martin Odersky Functional programming - Erick Mejer если кто-то прослушает какой-нибудь курс и покажет сертификат – 30 баллов Или если кто-то слушал ФП в Computer Science Center и может это продемонстрировать – тоже 30 баллов 4

  5. Про задачи Как сдавать задачи: Система тестированияhttp://ms8255.ru/fp Или можно присылать по почте, или приносить на листке Правила про задачи: Надо сдавать не позже начала пары Можно писать не (совсем) правильно Нельзя присылать очень похожие решения… 5

  6. На чем писать? • Я пишу на Haskell • Если есть желающие, можно F#, LISP (Clojure, Racket и т.д.), ML (OCaml), Scala, Erlangи т.д. (почти для всех задач) • А м.б. и Питон, Ruby и т.д. • Компиляторы – Haskell Platform, WinHugs, FP Haskell Center • На сайте документы про то, как начать работать с WinHugsи Haskell Platform

  7. Литература • Литература • См. ссылки на сайте • Роганова Н.А. «Функциональное программирование» – основы, очень просто • «Изучай Хаскел ради добра» • Г.Макеев «Основы функционального программирования на языке Haskell»

  8. Немного истории

  9. Кто придумал ФП? Alonzo Chirch • Примерно 1932 г. до первого компьютера! (1941, К.Цузе) Что такое алгоритм? Каким минимальным набором средств, можно описать любой алгоритм? Ответы: • Тьюринг: Машина Тьюринга • Черч:Лямбда-исчисление: Функции!

  10. Лисп John McCarthy • 1958 г. LISPЯзык высокого уровня #2! (После Фортрана) • Маленький и простой • Не используется GOTO и т.д. • Сборка мусора • Программы можно использовать, как данные

  11. Haskell и потом • Scheme, ML, OCAML … • 1990 – Haskell • C# 3.0 • F# • C++11 • Java 8 • Erlang • Scala • Python, Ruby и т.д.

  12. Основные темы ФП

  13. Что такое ФП? Wikipedia:“programming paradigm, that treats computation as the evaluation of mathematical functions and avoids state and mutable data.” • Т.е. мы себя ограничиваем • Не используем оператор присваивания • Все переменные const • Не используем for и т.д. • А.П.Ершов: Примерно как играть в волейбол с одной привязанной рукой • Зачем? • Меньше ошибок • Проще оптимизировать • Проще выполнять параллельно • И т.д. Убедительно? • John Hughes «Why Functional Programming Matters»«Если бы исключение оператора присваивания принесло такие огромные выгоды, то программисты на Фортране сделали бы это лет двадцать назад».

  14. Функции высшего порядка • Функция, параметр которой – тоже функция. Например: • integral(0, 1, sin) • draw(0, 1, cos) • forall(list, print); • Можно зайти очень далеко (и мы постараемся): • Функции, как результат функции • Сложные случаи (функция, которая возвращает функцию, которая возвращает функцию и т.д.) • Например, одна из функций, которую придумал Черч:λn.λf.λx. n (λg.λh. h (g f)) (λu. x) (λu. u)

  15. Ленивые вычисления, бесконечные списки • x = sin(y); идея: может быть, тут не вычислять ничего… … cout << x; … ивот только тут вычислить sin • И тоже постараемся далеко зайти… • Бесконечные списки Как найти n-ное число Фибоначчи? • Описать бесконечный список, в котором каждый элемент равен сумме двух предыдущих • Взять в этомсписке n-ный элемент

  16. Система типов Вывод типов • C#:var x = Math.Sin(1); • Не надо писать тип x – компилятор и сам может догадаться • И, опять же, попробуем далеко зайти) • Вообще не пишем типы (ну, почти совсем…). Но они есть – компилятор выводит их сам. Полиморфизм • То, что в С++ хотели ввести под именем concept (но не очень получилось)

  17. Фокусы • continuations • «вызвать функцию, апотом …» • Монады • Один из примеров: Выполняем последовательность действий до первой ошибки • М.б. еще что-то (lens, arrows)??

  18. Теория • Лямбда исчисление • Изоморфизм Карри-Ховарда • М.б. еще что-то?? (free theorems?)

  19. Это все действительно полезно знать? • Будете ли вы писать на Хаскеле? • Скорее всего, нет  • Будете ли вы использовать приемы ФП в обычных языках? • Скорее всего, да • М.б. полезные приемы • Просто как пример, Map/Reduce • Развивает сообразительность…

  20. Простые программы на Haskell

  21. Лексика • Комментарии -- это комментарий {-- Аэто многострочный комментарий --} • Имена • Первая буква имеет значение • x, sin – переменные, функции • Integer, True- имена типов, константы • Можно использовать кавычки • abc’

  22. Числа Как обычно: 563.1415926 3.0e9 • М.б. бесконечнозначные 2^100 2^1000 Операции как обычно: • + - * / • Для деления нацело с остатком функции div, mod • ^ - возведение в степень 2^1000 = 1071508607186267320948425049060001810561404811705533607443750388370351051124936122493198378815695858127594672917553146825187145285692314043598457757469857480394567774824230985421074605062371141877954182153046474983581941 267398767559165543946077062914571196477686542167660429831652624386837205668069376

  23. Логические значения • Сравнение • Не равно: /= • Остальное как обычно: < <= > >= == • True, False • && || not Пример:x*y < 0 && (y*y + x*x < 1)

  24. Функции Не совсем обычно! • Не пишутся ни запятые, ни скобкиsin xmod k 10 + div k 10 • Приоритет: сначала функции, потом операторы sin x*x– это(sin x) * x Совет:Непонятная ошибка  проверьте, правильно ли расставлены скобки • f g x – это (f g) x Т.е. скобки группируются слева направо. • sin sin 1 – это (sin sin) 1 (ошибка) • А когда это удобно? Позже обсудим…

  25. Как определить свою функцию • Самый простой пример: sqr x = x*x Потом: sqr 5 • Пример простой рекурсивной функции (Конечно же, это факториал:) fact 1 = 1 fact n = fact (n-1) * n • Порядок важен! fact n = fact (n-1) * n fact 1 = 1 // Досюда не дойдет:( • Одно ограничение, на первый взгляд непонятное: f n n = … // Так нельзя! • Переменная слева от = не может встречаться 2 раза (называется: линейность)

  26. Условный оператор.Где начинается следующее правило? • if условие then выражение else выражение abs x = if x > 0 then x else –x f x = x + if x > 0 then x else 0 • Откуда компилятор знает, где начинается следующее правило? • С первой позиции в строке новое правило • Строка начинается с пробела продолжение правила

  27. Операторы • Можно определять свои операторы i @@ j = i*i + j*j • Пример вызова 5 @@ 7 • Может использоваться любая последовательность символов (кроме зарезервированных типа -> и ::) • Обычные функции можно использовать, как инфиксный оператор • Надо взять в обратные кавычки (`) i `mod` 100

  28. Хвостовая рекурсияНакапливающие параметры

  29. Как вычисляется факториал fact 1 = 1 fact n = fact (n-1) * n fact 5 = fact 4 * 5 fact 4 = fact 3 * 4 fact 3 = fact 2 * 3 fact 2 = fact 1 * 2 fact 1 = 1 • Для fact 1000000 на стеке будет 1000000 вызовов 120 24 6 2 1

  30. Еще вариант факториала • Давайте сразу перемножать во время рекурсии fact n = fact’ n 1 fact' 1 p = p fact' np = fact’ (n-1) (n*p) fact' 5 1 = fact’ 4 (5*1) fact'4 5 = fact’ 3 (4*5) fact’ 3 20 = fact’ 2 (3*20) fact’ 2 60 = fact’ 1 (2*60) fact’ 1 120 =120 fact n = fact’ n 1 fact' n p = fact’ (n-1) n*p fact' 1 p = p • Две ошибки  5 1 4 5 3 20 2 60 1 120

  31. Хвостовая рекурсия • Если вызов функции – это последнее, что происходит при вычислении правило, то он называется хвостовым вызовом (tail call). • Если в некоторой функции все рекурсивные вызовы – хвостовые, то говорят, что в этой функции используется хвостовая рекурсия (tail recursion) • Студент X: пример хвостовой рекурсии:fact n = n * fact (n-1) • Нет! • Зачем нужна хвостовая рекурсия? • Можно реализовать более эффективно (и во многих языках так и реализовано) • Но не в Haskell… • Иногда просто удобнее писать (накапливающие параметры).

  32. Накапливающие параметры fact' 1 p = p fact' np = fact’ (n-1) (n*p) • Функция использует p, чтобы передавать в рекурсивный вызов информацию о частично вычисленном значении. • Называется накапливающие параметры (accumulating parameters) Еще пример: • sumprod n = 1 + 2 + … + n / 1*2*3*…*n sumprod n = sumprod’ n 0 1 sumprod' 0 s p = s / p sumprod' n s p = sumprod’ (n-1) (s+n) (p*n)

  33. Списки

  34. Списки • Основной тип данных • (и почти во всех функциональных языках) • Примеры: [1, 2, 3] [3.5, 2.123, 98.14] [True, False] • Элементы д.б. одного типа! [1, True, 2] -- Ошибка!

  35. Как создавать списки Оператор : • Оператор : • Приписать элемент в начало 1 : [2,3]  [1,2,3] • Пример: f 0 = [] f n = n : f (n-1) • Список чисел от n до 1 • Кстати:[a..b] – числа от a до b с шагом 1 • На самом деле, [1,2,3] – это просто сокращение! • [1, 2, 3] – сокращение для 1:2:3:[] • Так и хранится: : / \ 1 : / \ 2 : / \ 3 []

  36. Как обрабатывать списки – способ 1 • head – первый элемент списка • tail – все,кроме первого элемента («хвост») head [1,2,3]  1 tail [1,2,3]  [2,3] • Пример: сумма элементов списка sum [] = 0 sum xs = head xs + sum(tail xs) Замечания: • Типичные имена для списков в Haskel: xs, ysи т.д. • sum – на самом деле, есть такая стандартная функция

  37. ШаблоныКак обрабатывать списки – способ 2 sum [] = 0 sum (x:xs) = x + sum xs • Слева от = м.б. выражение с переменными – шаблон (pattern) • Шаблоны м.б. довольно сложным • Примеры: f [x, y, z] f [1, y, 2] f (x:y:xs) f (x:1:xs) Замечания: • sum (x:xs) – скобки нужны! • Еще раз, правило линейности: • f [x, y, x] -- ошибка!

  38. Еще пример • product – произведение чисел списка (стандартная функция) product [] = 1 product (x:xs) = x * product xs • Снова факториал fact n = product [1..n] • Это стиль Haskell! • Fritz RuehThe Evolution of a Haskell Programmerhttp://www.willamette.edu/~fruehr/haskell/evolution.html

  39. ++ • Еще одна стандартная функция • Конкатенация - оператор ++ [1,2] ++ [3,4]  [1,2,3,4] [] ++ ys = ys (x:xs) ++ ys = x : (xs ++ ys) • Кстати: как приписывать в конец списка • xs : x • Нет!: приписывает только в начало! • xs ++x • Нет!++ работает только со списками! • xs ++ [x] • OK • Но O(n) – медленно!

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

  41. Пример: map • Взять синус от всех элементов списка sinAll [] = [] sinAll (x:xs) = sin x : sinAll xs • Взять косинус от всех элементов списка cosAll [] = [] cosAll (x:xs) = cos x : cosAll xs • Возвести все элементы списка в квадрат • :( Надо что-то делать! • map map f [] = [] map f (x:xs) = f x : map f xs • Примеры вызова map sin [1,2,3]  [sin 1, sin 2, sin 3] map sqr [1,2,3]  [1,4,9] • Функция высшего порядка!

  42. Лямбда-выражения • Почему в обычных языках (Паскаль, C) этим мало пользуются? • Еще задача: К каждому числу в списке приписать 7 справа. f x = 10 * x + 7 map f xs • Надо описывать вспомогательные функции – лень  • Надо придумывать имена – тоже лень  • Лямбда-выражение – функция без имени • \i -> 10*x + 7 map (\i -> 10*i+7) xs • Синтаксис: \ параметр1 параметр2 ->выражение • \ - то, что осталось от λ • Ограничения: • М.б. только одно правило (но case) • Естественно, не м.б. рекурсивно

  43. Разное

  44. trace, show import Debug.Trace … trace строка значение … • Возвращает значение • Печатает строку • Пример: height Empty = trace "!!!" (-1) • show • show 66  "66" • Не требует import, есть почти для всех обьектов • show [1,2,3]  "[1,2,3]" • Пример trace + show: fact i = trace (show i) i *fact (i-1)

  45. Функции высшего порядка в C#Как описыватьпараметры-функции • Как описывать параметры – функции • Как задавать значения для параметров-функций • Как описывать: Func<int, int> f • Func<тип1, тип2, … ,тип_результата> Func<int, double, bool> • Это сокращение для delegate • Специальные случаи: • Predicate<int> pred • функция с одним параметром и логическим значением • Action<int> act Action<int, double> act1 • Функция возвращает void

  46. Как задавать значения для параметров-функций • Что можно передавать в функцию с параметром-функцией? • Имя статического метода • Expression lambdaпараметр => выражение или (параметр, параметр, …) => выражение i => i*i (i, j) => i + j • Можно указывать типы (но обычно не нужно) (int i, int j) => i + j • Statement lambdaпараметр => блок или (параметр1, параметр, …) =>блок n => { int p = 0; for(int i=1;i<=n;i++) p*=i; return p; } • Есть еще возможности (delegate, не статические методы…)

  47. Пример static void PrintTable( Func<int, int> f, int n) { for (int i = 0; i <= n; i++) { Console.WriteLine("{0} {1}", i, f(i)); } } static int Cube(int i) { return i * i * i; } // Примеры вызова: PrintTable(Cube, 10); Func<int, int> sqr = i => i * i; PrintTable(sqr, 10); PrintTable(i => i*i, 10);

  48. Refential transparency • Что такое ‘побочный эффект’? • Прозрачность по ссылкам (referential transparency) … f 5 + … f 5 … • Вызовы с одинаковыми параметрами всегда дают одинаковые значения • Можно заменить на один вызов (с помощью let, например) Не очень понятно: • А как же случайные числа?? • А как же ввод/вывод??

More Related