fp intro

Preview:

DESCRIPTION

Введение в функциональное программирование, которое я рассказывал в #mcst

Citation preview

31.01.2014

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

ivan.glushkov@gmail.com!@gliush

Императивное программирование

✤ Последовательность модификаций состояния!

✤ начальное значение S0 (входные значения)!

✤ конечное значение Sn (конечное значение)!

✤ модификация с помощью команд присваивания!

✤ Sn = f(S0)!

✤ абстрагирование от низкоуровневых деталей

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

✤ вся программа - одно [матем.] выражение!

✤ выполнение - вычисление значения выражения!

✤ языковые конструкции для облегчения чтения и написания программ!

✤ абстрактная система для записи алгоритма -> перевод на императивный язык низкого уровня

Отличительные особенности ФП

✤ не используют “переменные”!

✤ нет оператора присваивания!

✤ нет циклов!

✤ функции - обычные значения!

✤ рекурсия!

✤ могут напрямую соответствовать матем. объектам

Примеры

✤ Всеми любимый пример “факториал”!

✤ Сама функция: foo n = if n == 0 then 1 else n * foo (n-1)!

✤ Матем. описание: f(n): n! n >= 0 ⏊ n < 0

Функции императивных языков

✤ значение зависит не только от аргументов!

✤ результатом могут быть побочные эффекты!

✤ два вызова могут приводить к разному результату!

✤ вывод: это не функции в математическом смысле

Лямбда-исчисление (lambda calculus)

✤ создана в начале 30х годов!

✤ формализация для написания программ!

✤ простая модель для рекурсии и вложенных сред!

✤ лямбда выражения (анонимные функции)!

Введение в лямбда-исчисление: лямбда-терм

✤ Переменные!

✤ Константы!

✤ Комбинации: применение функции S к аргументу T: (S T). И S и T - могут быть произвольными лямбда-термами!

✤ Абстракции произвольного лямбда терма S по переменной x: λ x . S!

✤ Exp = Var | Const | Exp Exp | λ Var . Exp!

✤ Представляется в виде дерева, а не строки. Поэтому любые договоренности написания - не часть формальной системы.

Введение в лямбда-исчисление: обзор

✤ Свободные и связанные переменные:S = (λ x y . x) (λ x . z x) => FV(S) = {z}, BV(S) = {x,y}!

✤ Подстановкиприменение λx.S к аргументу T дает S[x := T]!

✤ Каррирование (R -> R -> R) = (R -> (R -> R))(λ x y . x + y) 1 2 = (λ y . 1 + y) 2 = 1 + 2 = 3

Введение в лямбда-исчисление: преобразования

✤ Альфа-преобразование: λ x . S -> λ y . S [x := y], if y ∉ FV(T)!

✤ Бета-преобразование:(λ x .S) T -> S [x := T]!

✤ Эта-преобразование: λ x . T x -> T, if x ∉ FV(T)!

✤ позволяют переходить к эквивалентному терму!

✤ равенство лямбда-термов!

✤ редукция лямбда-термов, в том числе к “нормальной” форме

Введение в лямбда-исчисление: пример Bool значений и условий

✤ Bool - тип, представляющий функцию от двух переменныхtrue ~> λ x y . x false ~> λ x y . y!

✤ if E then E1 else E2 ~> E E1 E2 Пример:if true then E1 else E2 = true E1 E2 = (λ x y . x) E1 E2 = λ y . E1 = E1!

✤ not p = if p then false else true p and q = if p then q else false p or q = if p then true else q

Введение в лямбда-исчисление: пример натуральных чисел

✤ Любое натуральное число N - это выполнение функции suc n раз: n = suc (suc (suc … (0)) …)!

✤ Достаточно определитьsuciszeroчтобы поддержатьm + n m * n pre n

Введение в лямбда-исчисление: типизация

✤ дают ясное представление о функции, если знать область определения и значений!

✤ эффективность (int8, int64) по mem и по cpu!

✤ статическая проверка программ!

✤ модульность и скрытие данных!

✤ позволяют обойти некоторые мат. противоречия

типизация в ЯП

✤ строгая типизация - мягкая типизацияint a[] = {1,2,3,4.0}; /* c - it’s ok */let a = [1,2,3,4.0] - - haskell - not ok A = [1,2,3,4,”hello”, [“world”]]. % erlang - it’s ok!

✤ динамическая типизация - статическая типизация!

✤ полиморфизм типов!

✤ автоматический вывод типов

Типизированное лямбда-исчисление

✤ Каждый лямбда-терм имеет тип!

✤ терм S можно применить к терму T, если их типы правильно соотносятся (сильная типизация): S :: a -> b T :: aS T :: b!

✤ Базовые типы: Int, Bool!

✤ Конструктор типов: Int; Bool; Bool -> Bool; [Bool] -> Bool

Отложенные (ленивые) вычисления

✤ (λ x . x + x + x) (10 + 5):(10 + 5) + (10 + 5) + (10 + 5) - нормальная редукция(15 + 15 + 15) - передача по значению!

✤ Передача по значению обычно более эффективна необходима для гибридных языков!

✤ Вызов по необходимости позволяет исп. ленивые вычисления!

✤ bottom = bottom - - Haskell: никогда не завершитсяconst1 x = 1 - - нет необходимости проверять аргументconst1 bottom -> 1 const1 (1/0) -> 1!

✤ Плата: снижение эффективности при сохранении отложенных вычислений

Пример ленивых вычислений

✤ ones = 1 : onesnumsFrom n = n : numsFrom (n+1) square x = x^2squres = map square (numsFrom 1)!

✤ take 5 (numsFrom 1) -> [1,2,3,4,5]!

✤ take 5 squares -> [1,4,9,16,25]

real world функции

✤ как в чисто функциональном языке сделать print?!

✤ сравнение функции random: /* c-like, нет входа, случайный результат */ long random(void); - - haskell: generator as input, new generator as outputrandom :: RandomGen g => g -> (a, g)

Введение в haskell

✤ статическая типизация: тип объекта фиксируется в момент компиляции!

✤ строгая типизация (imp. статическая типизация): строго определенные типы для любых операцийприсваивание переменной только значения того же типа не допускается неявное преобразование типов!

✤ чистый язык: детерменированность и отсутствие побочных эффектов

Синтаксис haskell

✤ идентификаторы: someFunction, foo, foo’, abc123. Каждому идентификатору можно сопоставить тип!

✤ Знаки операций, приоритеты между ними: + , - , * , / , ++!

✤ clause функций factorial 0 = 1 factorial n = n * factorial (n-1)!

✤ guardsfactorial n | n == 0 = 1 | otherwise = n * factorial (n - 1)!

✤ indentation!

✤ backquote:div 10 5 -> 2 10 `div` 5 -> 2

Введение в haskell 2

✤ элементарные типы: Int, Bool, Char, Float!

✤ Конструкторы типов: кортежи (tuples), списки, random :: g -> (a,g)map :: (a->b) -> [a] -> [b]!

✤ алгебраические типы данных (ADT): data Maybe a = Just a | Nothing!

haskell tools

!

✤ hoogle search!

✤ ghci repl!

✤ ghc compiler extensions

Недостатки

✤ сложность восприятия!

✤ gc mem!

✤ gc cpu

списки как пример простоты “ядра языка” haskell

✤ Поддержка - на уровне библиотек.!

✤ Работа со списками[] [1,2,3] 1:[2,3] [1,2] ++ [3](1:(2:(3:([]))))!

✤ map :: (a -> b) -> [a] -> [b]foldl :: (a -> b -> a) -> a -> [b] -> ahead :: [a] -> a tail :: [a] -> [a]length :: [a] -> Int null :: [a] -> Bool!

✤ foldl (+) 0 [1,2,3,4] -> 10 map (^2) [1,2,3,4] -> [1,4,9,16]head [1,2,3,4] -> 1 tail [1,2,3,4] -> [2,3,4]

Вопросы?

✤ ivan.glushkov@gmail.com!

✤ facebook: gliush!

✤ twitter: @gliush

Recommended