190 likes | 419 Views
Лекция 25. ЗНАКОМСТВО С ФП. Функциональное vs И мперативное. P. Программа – это функция, входные данные – аргументы, выходные – возвращаемое значение. Различие функционального и императивного программирования в том, каким образом определяется функция.
E N D
Лекция 25 ЗНАКОМСТВО С ФП
ФункциональноеvsИмперативное P Программа – это функция, входные данные – аргументы, выходные – возвращаемое значение.Различие функционального и императивного программирования в том, каким образом определяется функция. • В императивном п. исполнитель перерабатывает входные данные в выходные, выполняя команды, из которых состоит программа. • В функциональном п. функция составляется из ограниченного набора встроенных в язык функций при помощи нескольких операций.
Базовые функции и операции В ФП базовыми являются функции, встроенные в язык, такие как сложение, умножение, и т.п. Базовые операции: R(x) = if U(x) then F(x) else G(x) – ветвление, R(x) = if U(x) then F(x) else R(x-1)– рекурсия, R(x) = F(G(x)) – композиция. Поскольку операции над функциями это тоже функции, а константы можно рассматривать как функции без параметров, то программирование состоит в комбинировании функций. В ФП нет изменяемых значений (т.е. переменных), следовательно, не может быть присваивания и циклов.
Выполнение функциональной программы Вычисление значения функции сводится к подстановке аргументов и замене заголовка функции на ее тело. Эту механическую работу и выполняет компьютер. Пример. sqr x = x * x -- программа, которую составил программист sqr 5 -- выражение, которое получает вычислитель sqr 5 = 5 * 5 – подстановка 5 вместо x 5 * 5 -- замена заголовка на тело функции 5*5 = 25 – часть определения встроенной функции умножения 25 – окончательный результат работы вычислителя
Язык Lisp Lisp = LISt Processing Язык Lisp создан в 1960 году Джоном Маккарти (McCarthy, John; р. 1927 ) в Массачусетском технологи-ческом институте на теоретическом фундаменте лямбда-исчисления, пред-ложенного еще в 1930 году известным американским логиком Алонзо Черчем. Дж. Маккарти и А.П. Ершов Снимок 1975 г.
Программа на Lisp (setq L `(8 5 13 11 10)) (defunsum (L) (cond ((null L) '0) (t (add (car L) (sum (cdr L)))) ) ) (div (sum L) '5) Базовые функции:cond — условная функция, проверяющая с помощью функции null пустоту списка; add — суммирование аргументов; car — извлечение первого элемента из списка; cdr — извлечение остатка списка (без первого элемента). Программа на Lisp имеет специфический вид из-за обилия скобок. За это студенты прозвали его «LotsofInfuriatingandSillyParenthesis» -
Язык Haskell В 1990 году группой математиков был предложен язык Haskell. Сейчас это один из наиболее популярных языков функционального программирования. Язык назван именем американского математика и логика Хаскелла Карри. Последняя версия языка — Haskell2012, но стандартом остаётся Haskell 98.
Ссылки http://dshevchenko.biz/hs/ - Денис Шевченко "О Haskell по-человечески" http://anton-k.github.io/ - Антон Холомьёв. Учебник по Haskell
Типы Haskell– строго типизированный язык. Встроенные типы: Integer, Int, Float, Double, Bool, Char. Пользовательский тип задается конструкторами значений, например: data Bool = True | False data Complex = Complex IntInt data – ключевое слово для определения типа. Конструкторы типа – тоже функции.
Определение функций Определение начинается с объявления типа функции. Затем следует левая и правая части определения, разделенные знаком =. Функция для вычисления факториала. fact:: Int -> Int fact x = if x == 0 then 1 else x * fact (x-1) Ветвление можно организовать по-другому. fact 0 = 1 fact x = x * fact (x-1)
Интерпретатор Haskell Скачать можно с http://www.haskell.org/platform/
Модули Программасостоитизмодулей (module),одинмодуль – одинфайл. • Имямодулясовпадает с именемфайла. Файлыимеютрасширение .hs. Имямодуляначинается с большойбуквы,напримерFirstModule.hs. -- шапка moduleИмя(определение1, определение2,..., определениеN) where importМодуль1(...) importМодуль2(...) ... -- определения определение1 определение2 ...
Функции многих переменных Строго говоря, в Хаскеле таких нет, поскольку они не нужны. Определение функции n аргументов можно свести к определению n функций от одного аргумента, и это называется каррированием.
Каррирование Пример. Определим функцию сложения двух чисел. sum x y = x + y Выражение sum x yозначает (sum x) y, а не sum (x, y), как можно подумать. Из этой записи видно, что sum x– это одноместная функция, которая получает x и возвращает другую одноместную функцию, которую потом применяют к y. Что делает эта другая функция? Она увеличивает на x свой аргумент. Таким образом, тип функции sum:: Int -> (Int -> Int). Скобки обычно опускают, т.к. стрелка считается правоассоциативной. sum:: Int -> Int -> Int sum x y = x + y
Частичное применение В ФП не вызывают функции, а применяют их, например, sum 2 3. В результате частичного применения каррированной функции получается другая функция, от меньшего числа аргументов.Например, sum 1 - это функция, которая увеличивает свой аргумент на 1. Ей можно дать название: inc = sum 1 и применять: inc 4 -- возвращает 5
Бинарные операторы Оператор – это особая форма применения функции. Вот пары одинаковых по смыслу выражений. 2 + 2(+) 2 2 x < y (<) x y x /= y (/=) x y Если бинарный оператор применяется в функциональной форме, знак операции заключают в скобки. Если функция двух аргументов применяется в операторной форме, имя функции заключается в обратные кавычки. func x y = ... func 5 2 5 `func` 2
Определение операторов • Бинарные операторы можно объявлять так же, как и функции. • Определим оператор «приближенно равно», проверяющий, что два числа отличаются не более, чем на 0.001: • (~=):: Double->Double->Bool • (~=) x y = abs (x - y) < 0.001 • Если в имени функции нет букв и цифр, то она автоматически считается инфиксным оператором. При объявлении ее имя нужно заключать в скобки.
Приоритет и ассоциативность Приоритет и ассоциативность бинарного оператора задается при помощи ключевых слов infix, infixlи infixr (слово infix употребляется, когда ассоциативность для операции не имеет смысла). infixr 9 . infixl 9 !! infixr 8 ^, ^^, ** infixl 7 *, /, `quot`, `rem`, `div`, `mod`, :%, % infixl 6 +, - infixr 5 ++ infix 4 ==, /=, <, <=, >=, >, `elem`, `notElem` infixr 3 && infixr 2 || infixl 1 >>, >>= infixr 1 =<< infixr 0 $, $!, `seq`
Самостоятельно Объявить функции: максимум из двух чисел максимум из трех чисел наибольший общий делитель n-й член ряда Фибоначчи сумма гармонического ряда: 1 + 1/2 + 1/3 + … + 1/n