Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекция ФилП.docx
Скачиваний:
16
Добавлен:
19.09.2019
Размер:
401.58 Кб
Скачать

Деревья – рекурсивные типы данных

Data BinTree a = Empty

| Node (BinTree a) a (BinTree a)

(BinTree a)

a

(BinTree a)

A

/ \

BinTree a BinTree a

Сделать дерево плоским

(вкладывает его в список)

flatten :: BinTree a -> [a]

flatten Empty = []

flatten (Node l v r) = flatten l ++

v : flatten r

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

Применим накапливающий параметр

flatten’ :: BinTree a -> [a]

flatten’= inorder t []

where

inorder Empty xs = xs

inorder (Node l v r) xs =

inorder l (v : inorder r xs)

Удаление элемента дерева

delT y Empty = Empty

delT y (Node l x r)

| y>x = Node l x (delT y r)

| y<x = Node (delT y l) x r

| x==y = rebuild l r

Легко выполнить поиск по дереву, мы каждый раз можем решить если элемент не совпадает со знач в узле, то мы можем решить в левой или правой ветви искать. Дерево упорядочено.

Если X==Y то из двух деревьев нужно построить одно дерево (rebuild).

Объединение двух деревьев

15

7

20

3

12

18

25

9

15

В левом дереве найдем самое правое значение, удалим его и с этим значением в корне построим общее дерево.

rebuild Empty r = r

rebuild l r = (Node l’ x r)

where (l’ , x) = rightmost l

rightmost самый правый, берет дерево и наход самый правый элемент, возвр пару значений l’ оставш чатсь дерева и x удаленный элемент.

Извлечение самого правого элемента

Самый правый элемент:

rightmost (Node l x Empty) = (l,x)

rightmost (Node l x r) = (Node l x r’ , y)

where (r’,y) = rightmost r

append :: [a]->[a]->[a]

[1,2,3]

Такой вид полиморфизма(аппенд) слишком общий и он не подходит для случая перезагружаемых операторов.

(==) :: a->a->a нельзя, т.к. не все значения можно проверять на равенство.

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

Название класса пишется с большой буквы, в нем надо указать типовую переменную обязательно, член класса тоже и методы присущие данному классу. Для каждого члена класса нужно определить конкретные методы.

*начинается с ключевого слова instance. Eq – класс, включает тип Int.

Int Eq встроенная ф, которая проверяет на равенство целочисленные значения.

Аналогично тип для вещественных чисел в классе.

След пример это проверка на равенство двух деревьев. Элементы хранящиеся в дереве должны принадлежать к классу Eq.

Пример, если еть множества заданные списками то их можно проверять на равенство написав для этого соответ методы.

Допустим,

data Set a = Set [a]

instance (Eq a)=>Eq(Set a) where

(Set []) == (Set [])= True // два пустых множества равны

(Set []) == (Set (x:xs))= False

(Set (x:xs)) == (Set []) = False

(Set xs) == (Set ys) = .. нужно проверить что каждый элемент из xs принадлежит ys и каждый элемент ys принадлежит xs.

В классах можно исп методы по умолчанию.

Эти методы можно переопределить если есть более эффективный метод или можно оставить метод в общем виде.

На слайде пример метода по умолчанию x/=y он реал как not (x==y)

Если в это определение класса добавить x==y = not (x/=y) (так и сделано в станд библ) то для включения элемента в класс достаточно определить любой из методов.

Наследование

class (Eq a) => Ord a where

(<), (<=), (>), (>=) :: a -> a -> Bool

min, max :: a -> a -> a

Eq для Ord – суперкласс,

Ord для Eqподкласс.

Класс ord, элементы которого строго упорядочены и их можно проверят на больше меньше. Он явл подклассом класса Eq, он наследует проверку на равно и неравно.

Если пишем ф сортировки sort ord a => [a] -> [a]

Множественное наследование

class (Eq a, Show a) => C a where ...

Члены класса С наследуют операции из Eq и из Show .

Здесь приведен станд класс Show, в него входят те типы, значения которых можно представить в форме строки.

Есть еще класс Read, класс, элементы которого можно прочитать из строки.

data T …

Derioing Show

Строки

Строка – это список элементов типа Char;

[‘h’,’I’]

Более компактная запись:

“hi”.

a::Char

a = ‘x’

полезные функции

isSpace, isUpper, isLower, isAlpha, isDigit, isAlpanum:: Char->Bool

isSpace c = c == ‘ ‘ || c == ‘\t’ || c == ‘\n’

isUpper c = c >= ‘A’ && c <= ‘Z’

isLower c = c >= ‘a’ && c<= ‘z’

isAlpha c = isUpper c || isLower c

isDigit c = c >= ‘0’ && c <= ‘9’

isAlpanum c = isAlpha c || isDigit c

digitValue c =

| isDigit c = ord c – ord’0’

digitChar :: Int ->Char

digitChar n = chr (n+ord ‘0’)

toUpper:: Char ->Char

toUpper c

| isLower c

= chr (ord c – ord ‘a’ + ord ‘A’)

| otherwise = c

Форматирование числf

5 678

iterate (‘div’ 10)

[5678, 567, 56, 5, 0, 0, 0, …]

takeWhile (/=0)

[5678, 567, 56, 5]

map (`rem` 10)

[8,7,6,5]

reverse

[5,6,7,8]

map digitChar

“5678”

Здесь предполагается строгая последовательность действий.

Примерим оператор композиция функций

f :: a->b

g :: c -> a

(.) :: (a->b) -> (c->a) -> c -> b

(f . g) x = f (g x)

Те функции которые мы описали можно соединить в конвейер и получить ф, форматирующую число.