Wykład 9 Funktory (moduły sparametryzowane)

Podobne dokumenty
Wykład 8. Moduły. Zdzisław Spławski Programowanie funkcyjne 1

Wstęp do Programowania potok funkcyjny

Wstęp do Programowania potok funkcyjny

Obiektowy Caml. Paweł Boguszewski

Podstawy programowania 2. Temat: Drzewa binarne. Przygotował: mgr inż. Tomasz Michno

Struktury danych (I): kolejka, stos itp.

Wstęp do Programowania potok funkcyjny

Porządek symetryczny: right(x)

Wykład 5 Listy leniwe

Wstęp do Programowania potok funkcyjny

Imię i Nazwisko Data Ocena. Laboratorium 7

Semantyka i Weryfikacja Programów - Laboratorium 3

Algorytmy i struktury danych. Wykład 6 Tablice rozproszone cz. 2

Wstęp do programowania. Drzewa. Piotr Chrząstowski-Wachtel

Wykład 7 Porównanie programowania funkcyjnego i imperatywnego

Wykład 6. Drzewa poszukiwań binarnych (BST)

dodatkowe operacje dla kopca binarnego: typu min oraz typu max:

Wstęp do Programowania potok funkcyjny

Wysokość drzewa Głębokość węzła

Wstęp do Programowania potok funkcyjny

Wykład 2. Drzewa poszukiwań binarnych (BST)

Algorytmy i struktury danych. wykład 5

Wstęp do Programowania potok funkcyjny

Algorytmy i Struktury Danych.


Tabela wewnętrzna - definicja

Algorytmy i struktury danych. Wykład 4 Tablice nieporządkowane i uporządkowane

Drzewa binarne. Drzewo binarne to dowolny obiekt powstały zgodnie z regułami: jest drzewem binarnym Jeśli T 0. jest drzewem binarnym Np.

Drzewa poszukiwań binarnych

Teoretyczne podstawy informatyki

Plan bazy: Kod zakładający bazę danych: DROP TABLE noclegi CASCADE; CREATE TABLE noclegi( id_noclegu SERIAL NOT NULL,

Algorytmy i Struktury Danych. (c) Marcin Sydow. Słownik. Tablica mieszająca. Słowniki. Słownik uporządkowany. Drzewo BST.

Wykład 11 Podtypy a dziedziczenie

Programowanie obiektowe i C++ dla matematyków

Programowanie w C++ Wykład 6. Katarzyna Grzelak. 1 kwietnia K.Grzelak (Wykład 6) Programowanie w C++ 1 / 43

Programowanie w C++ Wykład 7. Katarzyna Grzelak. 23 kwietnia K.Grzelak (Wykład 7) Programowanie w C++ 1 / 40

Programowanie funkcyjne Wykład 13. Siła wyrazu rachunku lambda

Programowanie. Lista zadań nr 15. Na ćwiczenia 11, 19 i 23 czerwca 2008

Temat: Liniowe uporzdkowane struktury danych: stos, kolejka. Specyfikacja, przykładowe implementacje i zastosowania. Struktura słownika.

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

Algorytmy funkcjonalne i struktury danych

Cele. Definiowanie wyzwalaczy

Kompletna dokumentacja kontenera C++ vector w -

Algorytmy i struktury danych. Drzewa: BST, kopce. Letnie Warsztaty Matematyczno-Informatyczne

- nawiasy kwadratowe oznaczają, że to lista

Przypomnij sobie krótki wstęp do teorii grafów przedstawiony na początku semestru.

Wykład 7 Abstrakcyjne typy danych słownik (lista symboli)

Programowanie Funkcyjne. Marcin Kubica Świder,

Dynamiczne struktury danych

Programowanie obiektowe

Składnia funkcji i Rekurencja w języku Haskell

Przykładowe B+ drzewo

Wstęp do Programowania potok funkcyjny

Laboratorium z przedmiotu Programowanie obiektowe - zestaw 04

Programowanie w SQL procedury i funkcje. UWAGA: Proszę nie zapominać o prefiksowaniu nazw obiektów ciągiem [OLIMP\{nr indeksu}] Funkcje użytkownika

Składowane procedury i funkcje

structure foo :>PART TWO = struct exception NotImplemented datatype a tree = Leaf of a Node of a tree * a * a tree 1

Wstęp do Programowania potok funkcyjny

struktury danych dla operacji słownikowych

Algorytmy i Struktury Danych, 9. ćwiczenia

Wykład 2. Drzewa zbalansowane AVL i 2-3-4

Liczbowe funkcje rekurencyjne wielu zmiennych uczymy się na błędach

STL Standardt Template Library (wprowadzenie)

Oracle11g: Wprowadzenie do SQL

Wstęp do Programowania potok funkcyjny

Metody Kompilacji Wykład 3

Wykład 5 Wybrane zagadnienia programowania w C++ (c.d.)

Drzewa podstawowe poj

prowadzący dr ADRIAN HORZYK /~horzyk tel.: Konsultacje paw. D-13/325

Bazy danych 6. Klucze obce. P. F. Góra

< K (2) = ( Adams, John ), P (2) = adres bloku 2 > < K (1) = ( Aaron, Ed ), P (1) = adres bloku 1 >

Paradygmaty programowania

Listy powiązane zorientowane obiektowo

Drzewo. Drzewo uporządkowane ma ponumerowanych (oznaczonych) następników. Drzewo uporządkowane składa się z węzłów, które zawierają następujące pola:

Stos LIFO Last In First Out

Drzewa wyszukiwań binarnych (BST)

Sortowanie. Kolejki priorytetowe i algorytm Heapsort Dynamiczny problem sortowania:

Modelowanie hierarchicznych struktur w relacyjnych bazach danych

Wykład 5 funkcje i procedury pamiętane widoki (perspektywy) wyzwalacze

Oracle PL/SQL. Paweł Rajba.

Wykład 5. SQL praca z tabelami 2

Programowanie obiektowe i C++ dla matematyków

Kowalski Marcin Wrocław, dn Jaśkiewicz Kamil Bazy Danych 1 Podstawy Projekt Temat: Baza danych do zarządzania projektami

Teoretyczne podstawy informatyki

Tablice z haszowaniem

Kurs programowania. Wykład 9. Wojciech Macyna

Algorytmy i Struktury Danych.

Wstęp do Programowania potok funkcyjny

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

. Podstawy Programowania 2. Drzewa bst - część druga. Arkadiusz Chrobot. 12 maja 2019

Teoretyczne podstawy informatyki

Wstęp do programowania. Drzewa podstawowe techniki. Piotr Chrząstowski-Wachtel

Dynamiczne struktury danych

INTERNETOWE BAZY DANYCH materiały pomocnicze - wykład X

Systemy operacyjne. Laboratorium 8. Perl find

ALGORYTMY I STRUKTURY DANYCH

Wyszukiwanie w BST Minimalny i maksymalny klucz. Wyszukiwanie w BST Minimalny klucz. Wyszukiwanie w BST - minimalny klucz Wersja rekurencyjna

Wstęp do programowania

Obliczenia na stosie. Wykład 9. Obliczenia na stosie. J. Cichoń, P. Kobylański Wstęp do Informatyki i Programowania 266 / 303

Tablice z haszowaniem

Transkrypt:

Wykład 9 Funktory (moduły sparametryzowane) Składnia dla funktorów Sygnatura dla słownika Słownik jako binarne drzewo poszukiwań Słownik jako funkcja Zdzisław Spławski Programowanie funkcyjne 1

Programowanie małoskalowe i wielkoskalowe - analogie typ ~ sygnatura ( typ modułu, interfejs ) wartość ~ struktura ( moduł, implementacja ) funkcja ~ funktor Zdzisław Spławski Programowanie funkcyjne 2

Funktory - składnia Funktory można definiować podobnie jak funkcje: functor (Nazwa : sygnatura) -> struktura # module Para = functor (El : sig type t end) -> struct type para = El.t * El.t end;; module Para : functor (El : sig type t end) -> sig type para = El.t * El.t end Podobnie jak dla funkcji można użyć skrótu notacyjnego: module Nazwa1 (Nazwa2 : sygnatura) = struktura # module Para(El : sig type t end) = struct type para = El.t * El.t end;; module Para : functor (El : sig type t end) -> sig type para = El.t * El.t end Zdzisław Spławski Programowanie funkcyjne 3

Funktory - składnia Funktor może mieć dowolną liczbę parametrów: functor (Nazwa1 : sygnatura1) ->... functor (Nazwan : sygnaturan) ->struktura Tu również można użyć skrótu: module Nazwa (Nazwa1 : sygnatura1)... (Nazwan : sygnaturan) =struktura Aplikacja funktora do argumentów jest zapisywana zgodnie z poniższą składnią (każdy argument musi być umieszczony w nawiasach): module Nazwa = funktor (struktura1)... (strukturan) Funktory zapisujemy zawsze w postaci rozwiniętej. Nie ma odpowiednika postaci zwiniętej dla funkcji. Zdzisław Spławski Programowanie funkcyjne 4

Słowniki Słownikiem (ang. dictionary) nazywamy abstrakcyjny typ danych z operacjami wstawiania elementu do zbioru (insert), usuwania elementu ze zbioru (delete), oraz wyszukiwania elementu w zbiorze (lookup, search). Często przyjmuje się założenie, że klucze słownika należą do zbioru liniowo uporządkowanego. Czasem dla słownika używa się nazw lista lub tablica asocjacyjna. Efektywnymi strukturami służącymi do reprezentowania słowników są tablice z haszowaniem. Jako przykład napiszemy funktor dla słownika, reprezentowanego przez binarne drzewo poszukiwań. Binarne drzewa poszukiwań nie są polimorficzne względem typu klucza na zbiorze kluczy musi być zdefiniowany porządek liniowy. W języku OCaml (lub SML) można to wyrazić formalnie, parametryzując słownik modułem dla klucza, spełniającego odpowiednią sygnaturę ORDER. Sygnatura zawiera funkcję compare: t -> t -> order, porównującą dwa klucze i zwracającą jedną z wartości: LESS EQUAL GREATER. module type ORDER = sig type t val compare: t -> t -> order end;; Zdzisław Spławski Programowanie funkcyjne 5

Definicje pomocnicze # type order = LESS EQUAL GREATER;; (** Linearly ordered types **) # module type ORDER = sig type t val compare: t -> t -> order end;; module type ORDER = sig type t val compare : t -> t -> order end # module StringOrder: ORDER with type t = string = struct type t = string let compare s1 s2 = if s1<s2 then LESS else if s1>s2 then GREATER else EQUAL end;; module StringOrder : sig type t = string val compare : t -> t -> order end Zdzisław Spławski Programowanie funkcyjne 6

Sygnatura dla słownika # module type DICTIONARY = sig type key type 'a t exception DuplicatedKey of key val empty: 'a t val lookup: 'a t -> key -> 'a option val insert: 'a t -> key * 'a -> 'a t val delete: 'a t -> key -> 'a t val update: 'a t -> key * 'a -> 'a t end;; (*type of keys*) (*type of tables*) (*error in insert*) (*empty dictionary*) (*not necessary*) Zdzisław Spławski Programowanie funkcyjne 7

Drzewo poszukiwań binarnych 17 10 26 6 14 20 34 11 31 37 Zdzisław Spławski Programowanie funkcyjne 8

Słownik jako binarne drzewo poszukiwań (1) module Dictionary (Key: ORDER) : DICTIONARY with type key = Key.t = struct type key = Key.t type 'a t = Tip Node of key * 'a * 'a t * 'a t exception DuplicatedKey of key let empty = Tip let rec lookup tree key = match tree with Node(k,info,t1,t2) -> (match Key.compare key k with LESS -> lookup t1 key EQUAL -> Some info GREATER -> lookup t2 key ) Tip -> None ;; Zdzisław Spławski Programowanie funkcyjne 9

Słownik jako binarne drzewo poszukiwań (2) let rec insert tree (key, value) = match tree with Tip -> Node(key, value, Tip, Tip) Node(k,info,t1,t2) -> (match Key.compare key k with LESS -> Node(k, info, insert t1 (key,value), t2) EQUAL -> raise (DuplicatedKey key) GREATER -> Node(k, info, t1, insert t2 (key,value)) ) ;; Drzewo nie jest w żaden sposób wyważane, ponieważ cel przykładu jest inny. Zdzisław Spławski Programowanie funkcyjne 10

Słownik jako binarne drzewo poszukiwań (3) (* deletemin T returns a triple consisting of the least element y in tree T, its associated value and the tree that results from deleting y from T. *) let rec deletemin tree = match tree with Node(k,info,Tip,t2) -> (k,info,t2) (* This is the critical case. If the left subtree is empty, then the element at the current node is the min. *) Node(k,info,t1,t2) -> let (key,value,l) = deletemin t1 in (key,value,node(k,info,l,t2)) Tip -> failwith "Dictionary: implementation error" ;; Zdzisław Spławski Programowanie funkcyjne 11

Słownik jako binarne drzewo poszukiwań (4) let rec delete tree key = match tree with Tip -> Tip Node(k,info,t1,t2) -> match Key.compare key k with LESS -> Node(k,info, delete t1 key, t2) EQUAL -> ( match (t1, t2) with (Tip, t2) -> t2 (t1, Tip) -> t1 _ -> let (ki,inf,t_right) = deletemin t2 in Node(ki,inf,t1,t_right) ;; ) GREATER -> Node(k,info, t1, delete t2 key) Zdzisław Spławski Programowanie funkcyjne 12

Słownik jako binarne drzewo poszukiwań (5) let rec update tree (key, value) = match tree with Tip -> Node(key, value, Tip, Tip) Node(k,info,t1,t2) -> ( match Key.compare key k with LESS -> Node(k, info, update t1(key,value), t2) EQUAL -> Node(k, value, t1, t2) GREATER -> Node(k, info, t1, update t2(key,value)) ) ;; end;; (* Dictionary *) module Dictionary : functor (Key : ORDER) -> sig type key = Key.t and 'a t exception DuplicatedKey of key val empty : 'a t val lookup : 'a t -> key -> 'a option val insert : 'a t -> key * 'a -> 'a t val delete : 'a t -> key -> 'a t val update : 'a t -> key * 'a -> 'a t end Zdzisław Spławski Programowanie funkcyjne 13

Wykorzystanie funktora Dictionary (1) # module StringDict = Dictionary(StringOrder);; module StringDict : sig type key = StringOrder.t and 'a t = 'a Dictionary(StringOrder).t exception DuplicatedKey of key val empty : 'a t val lookup : 'a t -> key -> 'a option val insert : 'a t -> key * 'a -> 'a t val delete : 'a t -> key -> 'a t val update : 'a t -> key * 'a -> 'a t end # let ( < ) d (k,x) = StringDict.update d (k,x);; val ( < ) : 'a StringDict.t -> StringDict.key * 'a -> 'a StringDict.t = <fun> Zdzisław Spławski Programowanie funkcyjne 14

Wykorzystanie funktora Dictionary (2) # let dict = StringDict.empty;; val dict : 'a StringDict.t = <abstr> # let dict = dict < ("kot","cat") < ("slon","elephant") < ("pies","dog") < ("ptak","bird") ;; val dict : string StringDict.t = <abstr> # StringDict.lookup dict "pies";; - : string option = Some "dog" # StringDict.lookup dict "papuga";; - : string option = None # let dict = dict < ("papuga","parrot");; val dict : string StringDict.t = <abstr> # StringDict.lookup dict "papuga";; - : string option = Some "parrot" Zdzisław Spławski Programowanie funkcyjne 15

Słownik jako binarne drzewo poszukiwań (reprezentacja wewnętrzna) Nawiązując do dyskusji dotyczącej dzielenia i kopiowania wartości z wykładu 7, można zadać sobie pytanie, jak wygląda reprezentacja wewnętrzna binarnego drzewa poszukiwań po dodaniu nowego elementu. Języki funkcyjne (OCaml, SML, Haskell) wykorzystują tu kombinację współdzielenia i kopiowania (patrz następna strona). Kopiowane są wszystkie węzły znajdujące się na ścieżce poszukiwań, pozostałe węzły są dzielone. W naszej implementacji nie ma żadnych prób wyważania drzewa. Zdzisław Spławski Programowanie funkcyjne 16

Słownik po wykonaniu operacji wstawiania s2 = insert(s1,18, eighteen ) s1 s2 17 17 10 26 26 6 14 20 20 34 11 18 31 37 Dla uproszczenia rysunku pokazano tylko klucze elementów słownika. Zdzisław Spławski Programowanie funkcyjne 17

Słownik jako funkcja Z matematycznego punktu widzenia słownik jest funkcją odwzorowującą klucze w wartości. W językach funkcyjnych można to potraktować dosłownie i zaimplementować słownik jako funkcję. Taka implementacja będzie oczywiście bardzo nieefektywna (operacja usuwania powoduje wydłużenie słownika, podobnie jak operacja dodawania), ale zostanie poniżej przedstawiona jako ilustracja możliwości wykorzystania funkcji. Zdzisław Spławski Programowanie funkcyjne 18

module type KEY_TYPE = sig type t end;; Słownik jako funkcja (1) module DictionaryFun(Key:KEY_TYPE) : DICTIONARY with type key=key.t = struct type key = Key.t type 'a t = key -> 'a option exception DuplicatedKey of key;; let empty key = None;; let insert dict (key,item) = if dict key <> None then raise (DuplicatedKey key) else function k -> if k=key then Some item else dict k ;; let lookup dict key = dict key;; Zdzisław Spławski Programowanie funkcyjne 19

Słownik jako funkcja (2) let delete dict key k = if k = key then None else dict k;; let update dict (key,item) = function k -> if k=key then Some item else dict k;; end;; (* DictionaryFun *) module DictionaryFun : functor (Key : KEY_TYPE) -> sig type key = Key.t type 'a t exception DuplicatedKey of key val empty : 'a t val lookup : 'a t -> key -> 'a option val insert : 'a t -> key * 'a -> 'a t val delete : 'a t -> key -> 'a t val update : 'a t -> key * 'a -> 'a t end Zdzisław Spławski Programowanie funkcyjne 20

Wykorzystanie funktora DictionaryFun (1) # module StringDictFun = DictionaryFun(struct type t=string end);; module StringDictFun : sig type key = string type 'a t exception DuplicatedKey of key val empty : 'a t val lookup : 'a t -> key -> 'a option val insert : 'a t -> key * 'a -> 'a t val delete : 'a t -> key -> 'a t val update : 'a t -> key * 'a -> 'a t end # let ( < ) d (key,value) = StringDictFun.insert d (key,value);; val ( < ) : 'a StringDictFun.t -> StringDictFun.key * 'a -> 'a StringDictFun.t = <fun> Zdzisław Spławski Programowanie funkcyjne 21

Wykorzystanie funktora DictionaryFun (2) # let dict = StringDictFun.empty;; val dict : 'a StringDictFun.t = <abstr> # let dict = dict < ("kot","cat") < ("slon","elephant") < ("pies","dog") < ("ptak","bird");; val dict : string StringDictFun.t = <abstr> # StringDictFun.lookup dict "pies";; - : string option = Some "dog" # StringDictFun.lookup dict "papuga";; - : string option = None # let dict = dict < ("papuga","parrot");; val dict : string StringDictFun.t = <abstr> # StringDictFun.lookup dict "papuga";; - : string option = Some "parrot" Zdzisław Spławski Programowanie funkcyjne 22

Zadania kontrolne 1. Napisz program pokazujący, że operacja insert dla binarnego drzewa poszukiwań zwraca drzewo o strukturze pokazanej na stronie 17. 2. Napisz funktor dla słownika reprezentowanego przez listę skończoną, zgodny z sygnaturą podaną na wykładzie (elementy w liście powinny być uporządkowane według kluczy). Wykorzystując ten funktor utwórz dwa konkretne słowniki z różnymi typami kluczy i przetestuj je. Zdzisław Spławski Programowanie funkcyjne 23