1 Эффективность рекурсивных функций. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. -- Вычисление.

Презентация:



Advertisements
Похожие презентации
1 Глава 2. Средства функционального программирования Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования.
Advertisements

1 Списки в языке Haskell. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. [] -- пустой список [1, 2,
1 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Еще один пример функциональной программы
1 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Потоки. «Завязывание узлов» Часто обработку данных.
1 Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования Введение в язык Haskell История языка Haskell.
1 Кубенский А.А. Функциональное программирование. Глава 4. Основы лямбда-исчисления Рекурсия в лямбда-исчислении fac = λn.(if (= n 0) 1 (* n (fac.
1 Кубенский А.А. Функциональное программирование. Глава 5. Системы исполнения функциональных программ. Глава 5. Системы исполнения функциональных программ.
1 Д.з. 2 maxlist Не совсем правильное решение maxlist [x] = x maxlist (x:xs) = if x > maxlist xs then x else maxlist xs maxlist [1..100] – очень долго.
1 Кубенский А.А. Функциональное программирование. Глава 3. Стили функционального программирования. Глава 3. Стили функционального программирования 3.1.
1 Д.з. minlist - 1 Большинство решало так: minlist (x:xs) = minlist xs x minlist [] m = m minlist (x:xs) m = if x < m then minlist xs x else minlist xs.
1 Д.з. Shape – типичные ошибки contains (Circle r x y) a b = if (sqrt ((x-a)^2+(y-b)^2)) Double contains:: a -> Double -> Double -> Bool instance Shape.
1 Д.з. isosc – типичные замечания… 1. Считаем длину: sqrt ((x1-x2)^2 + (y1-y2)^2) sqrt не надо! 2. if (x1-x2)^2 + (y1-y2)^2 == (x1-x3)^2 + (y1-y3)^2 ||
Рекурсивная обработка списков1 Структуры и алгоритмы обработки данных, 1 Лекция 3 Рекурсивная обработка списков 1.Представление и реализация.
1 Кубенский А.А. Функциональное программирование. Глава 5. Системы исполнения функциональных программ. Глава 5. Системы исполнения функциональных программ.
Древовидная модель оказывается довольно эффективной для представления динамических данных с целью быстрого поиска информации. Деревья являются одними из.
1 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Потоки. «Завязывание узлов» Напишем программу для.
Язык функционального программирования Haskell Выполнила: Шатохина Е.В. ПИБ-41.
Лекция Неполная спецификация и недетерминизм. Let- и Case-выражения.
Деревья1 Структуры и алгоритмы обработки данных, 1 Лекция 5 ДЕРЕВЬЯ 1.Определения дерева, леса, бинарного дерева. Скобочное представление 2.Спецификация.
1 Д.з.. coins Решение 1 coins n = [[i, k, j] | i<-[0..n], j<-[0..n], k<-[0..n], i*2+j*3+k*5 == n] Решение 2 coins n = [[i, k, j] | i<-[0.. n `div` 2],
Транксрипт:

1 Эффективность рекурсивных функций. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. -- Вычисление числа Фибоначчи, заданного порядковым номером fib :: Integer -> Integer fib 1 = 1 fib 2 = 1 fib n = fib (n-1) + fib (n-2) fib 6 fib 5 + fib 4 (fib 4 + fib 3) + fib 4 ((fib 3 + fib 2) + fib 3) + fib 4 (((fib 2 + fib 1) + fib 2) + fib 3) + fib 4 (((1 + 1) + 1) + (fib 2 + fib 1)) + fib 4 (3 + 2) + (fib 3 + fib 2) (3 + 2) + ((fib 2 + fib 1) + 1) (3 + 2) + ((1 + 1) + 1) 8 f 1 = f 2 = 1 f n = f n-1 + f n-2 при n > 2

2 Эффективность рекурсивных функций. Концевая рекурсия. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. fib :: Integer -> Integer fib' :: Integer -> Integer -> Integer -> Integer -> Integer fib' n k fk fk1 | k == n = fk | k < n = fib' n (k+1) (fk+fk1) fk fib 1 = 1 fib n = fib' n fib 6 fib' fib' fib' fib' fib' factorial :: Integer -> Integer factorial 0 = 1 factorial n = n * factorial (n-1) factorial :: Integer -> Integer factorial' :: Integer -> Integer -> Integer factorial n = factorial' n 1 -- (factorial' n f) == (f * n!) factorial' n f | n == 0 = f | n > 0 = factorial' (n-1) (n*f)

3 Списки в языке Haskell. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. [] -- пустой список [1, 2, 3] -- список из заданых элементов 1:[2, 3] -- присоединение головного элемента к списку 1:(2:(3:[])) -- создание списка с помощью конструктора ':' [1..n] -- создание списка с помощью арифметической прогрессии [2, 4..20] -- арифметическая прогрессия с заданной разностью Типы списков [Char] -- список из символов (строка: "List" == ['L','i','s','t']) [(Char, Int)] -- список из кортежей: [('L', 1), ('i', 2), ('s', 3)] [[Int]] -- список из списков: [[1, 2], [3, 5..10], []] [Integer] -- список из целых чисел: [1..10] Функция суммирования элементов списка sumList :: [Integer] -> Integer sumList [] = 0 sumList (x:s) = x + sumList s sumList [1, 3, 6] 1 + sumList [3, 6] sumList [6] sumList [] 10

4 Еще один способ вычисления факториала. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. factorial :: Integer -> Integer factorial n = product [1..n] Несколько стандартных операций над списком и их определения. head :: [a] -> a head (x:ls) = x head [] = error "head: empty list" tail :: [a] -> [a] tail (x:ls) = ls tail [] = error "tail: empty list" length :: [a] -> Int length (x:ls) = 1 + length ls length [] = 0 null :: [a] -> Bool null (x:ls) = False null [] = True

5 Более сложные функции обработки списков. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. last :: [a] -> a last [] = error "last: empty list" last [x] = x last (x:ls) = last ls init :: [a] -> [a] init [] = error "init: empty list" init [x] = [] init (x:ls) = x : init ls (!!) :: [a] -> Int -> a [] !! _ = error "(!!): empty list" (x:ls) !! 0 = x (x:ls) !! n = ls !! (n-1) (++) :: [a] -> [a] -> [a] [] ++ ls = ls (x:l1) ++ l2 = x : (l1 ++ l2) reverse :: [a] -> [a] reverse' :: [a] -> [a] -> [a] reverse ls = reverse' ls [] reverse' [] l = l reverse' (x:ls) l = reverse' ls (x:l)

6 Еще некоторые стандартные функции обработки списков. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. sum :: Num a => [a] -> a sum [] = 0 sum (x:t) = x + sum t take :: Int -> [a] -> [a] take _ [] = [] take n _ | n [a] -> a maximum [] = error maximum: empty list" maximum [x] = x maximum (x:t) = max x (maximum t) zip :: [a] -> [b] -> [(a, b)] zip [] _ = [] zip _ [] = [] zip (e1:t1) (e2:t2) = (e1, e2) : zip t1 t2 unzip :: [(a,b)] -> ([a],[b]) unzip [] = ([], []) unzip ((e1,e2):t) = (e1:tail1, e2:tail2) where (tail1,tail2) = unzip t

Определение новых типов данных. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. Определение синонимов для типов type String = [Char] type Coord = (Double, Double) type Pair a = (a, a) type Complex = Pair Double Использование синонимов find :: String -> Char -> Int find [] _ = -1 find (x:s) y | x == y = 0 | otherwise = 1 + find s y distance :: Coord -> Coord -> Double distance (x1, y1) (x2, y2) = sqrt ((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1)) complexAdd :: Complex -> Complex -> Complex complexAdd (r1, i1) (r2, i2) = (r1+r2, i1+i2) swap :: Pair a -> Pair a swap (x, y) = (y, x)

Определение новых типов данных. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. Определение конструкторов data WeekDay = Sun | Mon | Tue | Wed | Thu | Fri | Sat data Bool = False | True Использование конструкторов weekend :: WeekDay -> Bool weekend Sun = True weekend Sat = True weekend _ = False Конструкторы с параметром data Coord = Point Double Double data Pair a = Couple a a Использование конструкторов с параметрами distance :: Coord -> Coord -> Double distance (Point x1 y1) (Point x2 y2) = sqrt ((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1)) swap :: Pair a -> Pair a swap (Couple x y) = Couple y x data Coord = Coord Double Double data Pair a = Pair a a distance :: Coord -> Coord -> Double distance (Coord x1 y1) (Coord x2 y2) = sqrt ((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1)) swap :: Pair a -> Pair a swap (Pair x y) = Pair y x

9 Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. Сложные типы данных. data IntList = Nil | Cons Integer IntList sumList :: IntList -> Integer sumList Nil = 0 sumList (Cons e ls) = e + sumList ls data List a = Nil | a :+: (List a) sumList :: List Integer -> Integer sumList Nil = 0 sumList (e :+: ls) = e + sumList ls sumList :: (Num a) => List a -> a sumList Nil = 0 sumList (e :+: ls) = e + sumList ls data [a] = [] | a : [a] sumList :: (Num a) => [a] -> a sumList [] = 0 sumList (e : ls) = e + sumList ls Сортировка списка. insert :: (Ord a) => a -> [a] -> [a] insert elem [] = [elem] insert elem | elem < x = elem:list | otherwise = x:(insert elem s) bubble :: (Ord a) => [a] -> [a] bubble [] = [] bubble (x:s) = insert x (bubble s)

10 Определение и обработка двоичного дерева. Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. data Tree a = Empty | Node (Tree a) a (Tree a) A BC DEF myTree :: Tree Char myTree = Node (Node (Node Empty 'D' Empty) 'B' Empty) 'A' (Node (Node Empty 'E' Empty) 'C' (Node Empty 'F' Empty)) height :: Tree a -> Int height Empty = 0 height (Node t1 _ t2) = 1 + max (height t1) (height t2)

11 Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. Сортировка с помощью двоичного дерева buildflatten sort :: (Ord a) => [a] -> [a] build :: (Ord a) => [a] -> Tree a flatten :: Tree a -> [a] sort ls = flatten (build ls)

12 Кубенский А.А. Функциональное программирование. Глава 1. Элементы функционального программирования. Программа сортировки с помощью двоичного дерева. data Tree a = Empty | Node (Tree a) a (Tree a) sort :: (Ord a) => [a] -> [a] build :: (Ord a) => [a] -> Tree a insert :: (Ord a) => a -> Tree a -> Tree a flatten :: Tree a -> [a] sort ls = flatten (build ls) build [] = Empty build (e:ls) = insert e (build ls) insert e Empty = Node Empty e Empty insert e (Node t1 n t2) | e < n = Node (insert e t1) n t2 | e >= n = Node t1 n (insert e t2) flatten Empty = [] flatten (Node t1 n t2) = (flatten t1) ++ (n : (flatten t2))

13 Глава 2. Средства функционального программирования Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования Функции высших порядков sqr :: Integer -> Integer sqr x = x * x source = [1, 2, 5, 7, 11] dest = [1, 4, 25, 49, 121] sqr dest = map sqr source map :: (Integer -> Integer) -> [Integer] -> [Integer] map _ [] = [] map f (x:ls) = (f x) : (map f ls) map :: (a -> b) -> [a] -> [b]

14 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Определение функций с помощью λ-выражений λ-исчисление Черча – исчисление безымянных функций sqr : λx.* x x sqr = \x -> (x * x)

15 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Более сложная функция, заданная с помощью λ-выражения factorial :: Integer -> Integer factorial = \n -> case n of 0 -> 1 n -> n * factorial (n-1) Конструкция case – общая форма задания выбора по образцу case expr of patt 1 | cond 11 -> expr 11 | cond 12 -> expr patt 2 | cond 21 -> expr 21 | cond 22 -> expr

16 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Еще один пример функции высшего порядка source = [ ] ,func =seed = (+)0, +, +, += func = (:)seed = [] 1 : (2 : (5 : (7 : (11 : [])))) = [1, 2, 5, 7, 11] foldr :: (a -> b -> b) -> b -> [a] -> b foldr func seed [] = seed foldr func seed (x:ls) = func x (foldr func seed ls)

17 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. С помощью функций высшего порядка можно программировать. factorial :: Integer -> Integer factorial n = foldr (*) 1 [1..n] search :: (Eq a) => a -> [a] -> Bool search e list = foldr (||) False (map (\x -> x == e) list) search 5 [1, 2, 5, 7, 11] foldr (||) False (map (\x -> x == 5) [1, 2, 5, 7, 11]) foldr (||) False [False, False, True, False, False] False || (False || (True || (False || (False || False)))) join1 :: [a] -> [a] -> [a] join1 [] list = list join1 (x:ls) list = x : (join1 ls list) join2 :: [a] -> [a] -> [a] join2 lis1 lis2 = foldr (:) lis2 lis1 True

18 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Еще несколько полезных функций высших порядков. -- "левая вставка" – еще один способ свертки списка foldl :: (b -> a -> b) -> b -> [a] -> b foldl _ seed [] = seed foldl f seed (x:ls) = foldl f (f seed x) ls reverse :: [a] -> [a] reverse list = foldl app [] list where app l x = x:l flip :: (a -> b -> c) -> (b -> a -> c) flip f = f' where f' x y = f y x reverse :: [a] -> [a] reverse list = foldl (flip (:)) [] list :: (b -> c) -> (a -> b) -> (a -> c) = fg where fg x = f (g x) sqr :: (Num a) => a -> a sqr a = a * a power4 :: (Num a) => a -> a power4 = comp sqr sqrsqr. sqr comp comp f g (.) f. g

19 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Еще несколько полезных функций высших порядков. -- свертки без "зерна" foldl1, foldr1 :: (a -> a -> a) -> [a] -> a foldl1 _ [x] = x foldl1 f (x:ls) = foldl f x ls foldr1 _ [x] = x foldr1 f (x:ls) = f x (foldr1 f ls) all, any :: (a -> Bool) -> Bool all f list = foldr (&&) True (map f list) any f list = foldr (||) False (map f list) takeWhile :: (a -> Bool) -> [a] -> [a] takeWhile _ [] = [] takeWhile f (x:ls) | f x = x : takeWhile f ls | otherwise = [] zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] zipWith _ [] _ = [] zipWith _ _ [] = [] zipWith f (e1:t1) (e2:t2) = (f e1 e2) : zipWith f t1 t2 -- кстати, zip list1 list2 = zipWith (,) list1 list2

20 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Свертки сложных структур данных. data Tree a = Empty | Node (Tree a) a (Tree a) A BC DEF Правосторонний обход этого дерева: F, C, E, A, B, D Функция, осуществляющая свертку в порядке правостороннего обхода: foldTree :: (a -> b -> b) -> b -> Tree a -> b foldTree _ seed Empty = seed foldTree f seed (Node t1 n t2) = foldTree f (f n (foldTree f seed t2)) t1 t1 = foldTree (++) seed t1 => D ++ (B ++ (A ++ (E ++ (C ++ (F ++ seed))))) «Разглаживание» дерева с помощью foldTree: flatten :: Tree a -> [a] flatten t = foldTree (:) [] t

21 Кубенский А.А. Функциональное программирование. Глава 2. Средства функционального программирования. Сортировка с помощью дерева: используем функции высших порядков. build [] = Empty build (e:ls) = insert e (build ls) flatten Empty = [] flatten (Node t1 n t2) = (flatten t1) ++ (n : (flatten t2)) data Tree a = Empty | Node (Tree a) a (Tree a) sort :: (Ord a) => [a] -> [a] build :: (Ord a) => [a] -> Tree a insert :: (Ord a) => a -> Tree a -> Tree a flatten :: Tree a -> [a] sort ls = flatten (build ls) insert e Empty = Node Empty e Empty insert e (Node t1 n t2) | e < n = Node (insert e t1) n t2 | e >= n = Node t1 n (insert e t2) build list = foldr insert Empty list flatten tree = foldTree (:) [] tree foldTree :: (a -> b -> b) -> b -> Tree a -> b foldTree _ seed Empty = seed foldTree f seed (Node t1 n t2) = foldTree f (f n (foldTree f seed t2)) t1