Tisztán funkcionális adatszerkezetek (folytatás)

Hasonló dokumentumok
Tisztán funkcionális adatszerkezetek

Tisztán funkcionális adatszerkezetek (folytatás)

Tulajdonságalapú tesztelés

Programozás burritokkal

DSL-eket kétféleképpen szoktak megvalósítani:

Funkcionális Nyelvek 2 (MSc)

2018, Funkcionális programozás

S2-01 Funkcionális nyelvek alapfogalmai

Lineáris belsőpontos Newton-iteráció

FUNKCIONÁLIS PROGRAMOZÁS ELŐADÁS JEGYZET

Funkcionális programozás

2016, Funkcionális programozás

2016, Funkcionális programozás

FUNKCIONÁLIS PROGRAMOZÁS

Fejlett programozási nyelvek C++ Iterátorok

2018, Funkcionális programozás

HASKELL. Tartalom előadás

Tartalom előadás

Párhuzamos programozás Haskellben (folytatás)

Dinamikus adatszerkezetek. 2D generikus tömb: C++ 2D generikus tömb: C++

Dinamikus adatszerkezetek. 2D generikus tömb: C++ 2D generikus tömb: C++ 2D tömb: Java versus C++ 2D tömb: Java.

2019, Funkcionális programozás. 5. el adás. MÁRTON Gyöngyvér

Adatszerkezetek és algoritmusok

List<String> l1 = new ArrayList<String>(); List<Object> l2 = l1; // error

Logikai és funkcionális programozás funkcionális programozás modul

Doktori értekezés. Diviánszky Péter 2012.

Generikus osztályok, gyűjtemények és algoritmusok

A programozás alapjai előadás. Amiről szólesz: A tárgy címe: A programozás alapjai

Az F# nyelv erőforrásanalízise

Bevezetés a Programozásba II 11. előadás. Adatszerkezetek megvalósítása. Adatszerkezetek megvalósítása Adatszerkezetek

Felhasználó által definiált adattípus

1. Template (sablon) 1.1. Függvénysablon Függvénysablon példányosítás Osztálysablon

Generikus keresőfák Erlangban

Adatbázis-kezelés ODBC driverrel

2019, Funkcionális programozás. 2. el adás. MÁRTON Gyöngyvér

2019, Funkcionális programozás. 4. el adás. MÁRTON Gyöngyvér

Collections. Összetett adatstruktúrák

Oktatási segédlet 2014

Ugrólisták. RSL Insert Example. insert(22) with 3 flips. Runtime?

Feladat. Ternáris fa. Típusspecikáció. Reprezentáció. Absztrakt implementáció. Érdi Gerg EAF II. 4/3.

Programozási technológia

FUNKCIONÁLIS PROGRAMOZÁS GYAKORLAT JEGYZET

A lista eleme. mutató rész. adat rész. Listaelem létrehozása. Node Deklarálás. Létrehozás. Az elemet nekünk kell bef zni a listába

Önszervező bináris keresőfák

C# gyorstalpaló. Készítette: Major Péter

8. Gyakorlat SQL. DDL (Data Definition Language) adatdefiníciós nyelv utasításai:

C++ Standard Template Library (STL)

Java II. I A Java programozási nyelv alapelemei

Bevezetés a programozásba 2

2018, Funkcionális programozás

Bánsághi Anna 2014 Bánsághi Anna 1 of 33

A lista adatszerkezet A lista elemek egymásutániságát jelenti. Fajtái: statikus, dinamikus lista.

117. AA Megoldó Alfréd AA 117.

Láncolt Listák. Adat1 Adat2 Adat3 ø. Adat1 Adat2 ø Adat3

Kifejezések. Kozsik Tamás. December 11, 2016

OOP: Java 11.Gy: Enumok, beágyazott osztályok. 13/1 B ITv: MAN

Adattípusok. Max. 2GByte

Dinamikus láncolt lista 4. GYAKORLAT

Adattípusok. Max. 2GByte

Programok értelmezése

Programozási nyelvek II.: JAVA, 4. gyakorlat

Adatbázisok* tulajdonságai

Adatbázisok elmélete 10. előadás

Láncolt listák Témakörök. Lista alapfogalmak

SQL*Plus. Felhasználók: SYS: rendszergazda SCOTT: demonstrációs adatbázis, táblái: EMP (dolgozó), DEPT (osztály) "közönséges" felhasználók

Az arrow struktúra. Patai Gergely április 1.

2018, Funkcionális programozás

Bevezetés, a C++ osztályok. Pere László

Bevezetés a programozásba II. 5. Előadás: Másoló konstruktor, túlterhelés, operátorok

Informatikai Kar. 3. fejezet. alapismeretek. Giachetta Roberto

infix kifejezés a+b ab+ +ab postfix kifejezés prefix kifejezés a+b ab+ +ab a+b ab+ +ab Készítette: Szabóné Nacsa Rozália

Komputeralgebra rendszerek

Objektum elvű alkalmazások fejlesztése Kifejezés lengyel formára hozása és kiértékelése

Adatbázisok elmélete 9. előadás

Objektumok inicializálása

Számítástechnika II. BMEKOKAA Előadás. Dr. Bécsi Tamás

Széchenyi István Egyetem

Komputeralgebra rendszerek

van neve lehetnek bemeneti paraméterei (argumentumai) lehet visszatérési értéke a függvényt úgy használjuk, hogy meghívjuk

LUSTA KIÉRTÉKELÉS, LUSTA LISTA

Programozás alapjai. 5. előadás

STL gyakorlat C++ Izsó Tamás május 9. Izsó Tamás STL gyakorlat/ 1

SQL haladó. Külső összekapcsolások, Csoportosítás/Összesítés, Beszúrás/Törlés/Módosítás, Táblák létrehozása/kulcs megszorítások

Pénzügyi algoritmusok

Java II. I A Java programozási nyelv alapelemei

Java. Perzisztencia. ANTAL Margit. Java Persistence API. Object Relational Mapping. Perzisztencia. Entity components. ANTAL Margit.

Programozási nyelvek II.: JAVA, 4. gyakorlat

Táblakezelés: Open SQL Internal table. Tarcsi Ádám: Az SAP programozása 1.

2018, Funkcionális programozás

Programozás C++ -ban 2007/4

STL. Algoritmus. Iterátor. Tároló. Elsődleges komponensek: Tárolók Algoritmusok Bejárók

Feldspar: Nyelv digitális jelfeldolgozáshoz

Alkalmazott modul: Programozás

Tuesday, March 6, 12. Hasító táblázatok


Virtuális függvények (late binding)

Adatbázis-lekérdezés. Az SQL nyelv. Makány György

Adatbázis Rendszerek II. 5. PLSQL Csomagok 16/1B IT MAN

Fordított és szkript nyelvek összehasonlító elemzése. Sergyán Szabolcs

Bevezetés a Programozásba II 12. előadás. Adatszerkezetek alkalmazása (Standard Template Library)

Átírás:

Tisztán funkcionális adatszerkezetek (folytatás)

Rövid összefoglalás az eddigiekről A hatékony adatszerkezetek általában... [..] language-independent only in the sense of Henry Ford: Programmers can use any language as they want, as long as it s imperative. Chris Okasaki, Purely Functional Data Structures, 1996 Az imperatív adatszerkezetek viszont: Gyakran döntő mértékben támaszkodnak az elemek felülírására ( destructive update ) Ezáltal nem tisztán funkcionálisak, mivel azok mindig (automatikusan) perzisztensek: az adatszerkezet régi állapotai is elérhetőek Hatékony (megvalósítható) perzisztencia: lusta kiértékelés, memoization, amortizáció. [2..40]

Interlude: Zipper A zipper az adatszerkezet egy olyan ábrázolási módja, amely megkönnyíti annak bejárását és elemeinek módosítását. "gap buffer": ugyanazon pozícióhoz (kurzorhoz) tartozó beszúrások és törlések nyalábolása, optimalizációja az amortizált költsége kevés. Gyakran alkalmazzák nagyobb méretű adatszerkezetekben való mozgásra vagy fókuszálásra, például: Fókusz és ablakok elhelyezésének kezelése (xmonad) Szövegszerkesztők Tranzakciós szemantikával rendelkező állományrendszerek http://hackage.haskell.org/package/zfs Ez a megoldás tetszőleges rekurzívan definiált adatszerkezet (lista, fa stb.) esetén alkalmazható. [3..40]

Kétirányú listák: "List with Zipper" [4..40]

Kétirányú listák: "List with Zipper" [5..40]

Kétirányú listák: implementáció (1) newtype ZippList α = ZPL ([α], [α]) fromlist :: [α] ZippList α fromlist xs = ZPL ([], xs) tolist :: ZippList α [α] tolist (ZPL (xs, ys)) = reverse xs ++ ys get :: ZippList α [α] get (ZPL (_, ys)) = ys [6..40]

Kétirányú listák: implementáció (2) right :: ZippList α ZippList α right (ZPL (xs, (y : ys))) = ZPL (y : xs, ys) right zl = zl left :: ZippList α ZippList α left (ZPL ((x : xs), ys)) = ZPL (xs, x : ys) left zl = zl put :: Either α α ZippList α ZippList α put (Left e) (ZPL (xs, ys)) = ZPL (e : xs, ys) put (Right e) (ZPL (xs, ys)) = ZPL (xs, e : ys) putleft = put Left putright = put Right [7..40]

Kétirányú listák: implementáció (3) modify :: (α Maybe α) ZippList α ZippList α modify f (ZPL (xs, y : ys)) = ZPL $ case (f y) of Nothing (xs, ys) Just e (xs, e : ys) modify _ zl = zl update f = modify (Just f ) delete = modify (const Nothing) [8..40]

Kétirányú fák: "Tree with Zipper" [9..40]

Kétirányú fák: "Tree with Zipper" [10..40]

Kétirányú fák: "Tree with Zipper" [11..40]

Kétirányú fák: "Tree with Zipper" [12..40]

Kétirányú fák: implementáció (1) data Tree α = Branch (Tree α) (Tree α) Leaf α data TreeContext α = Top L (TreeContext α) (Tree α) R (Tree α) (TreeContext α) type Location α γ = (α, γ) type TreeLocation α = Location (Tree α) (TreeContext α) [13..40]

Kétirányú fák: implementáció (2) treeleft :: TreeLocation α TreeLocation α treeleft (Branch l r, c) = (l, L c r) treeright :: TreeLocation α TreeLocation α treeright (Branch l r, c) = (r, R l c) treetop :: Tree α TreeLocation α treetop t = (t, Top) treeup :: TreeLocation α TreeLocation α treeup (t, L c r) = (Branch t r, c) treeup (t, R l c) = (Branch l t, c) [14..40]

Kétirányú fák: implementáció (3) treeupmost :: TreeLocation α TreeLocation α treeupmost l@(t, Top) = l treeupmost l = treeupmost (treeup l) treechange :: TreeLocation α (Tree α Tree α) TreeLocation α treechange (t, c) f = (f t, c) Például: treeview :: TreeLocation α Tree α treeview (t, _) = t treechange ((treeright treeleft treetop) t) (const (Leaf 0)) [15..40]

Ráadás: Zipper monád newtype Zipper λ α = Zipper { unzipper :: State λ α } deriving (Functor, Applicative, Monad, MonadState λ) traverse :: Location α γ Zipper (Location α γ) α α traverse start tt = evalstate (unzipper tt) start move :: (Location α γ Location α γ) Zipper (Location α γ) α move f = do modify f gets fst change :: (α α) Zipper (Location α γ) α change f = do modify (λ (t, c). (f t, c)) gets fst [16..40]

Zipper monád: példa swaptree :: Zipper (TreeLocation α) (Tree α) swaptree = move swap where swap (t, R l c) = (l, L c t) swap (t, L c r) = (r, R t c) treemap :: (α Tree α) (Tree α Tree α Tree α) (Tree α Tree α) treemap leaf branch = λ t. (treetop t) traverse treemapm where treemapm = do t gets fst case t of Branch do move treeleft l mod treemapm swaptree r mod treemapm move treeup (change const) (branch l mod r mod ) Leaf x return (leaf x) [17..40]

FingerTree (intuíció) [18..40]

FingerTree (intuíció) [19..40]

FingerTree (intuíció) [20..40]

FingerTree (intuíció) [21..40]

FingerTree (intuíció) [22..40]

FingerTree (intuíció) [23..40]

FingerTree (intuíció) [24..40]

Implementáció: társított (indexelt) típusszinonimák {-# LANGUAGE TypeFamilies, KindSignatures #-} class Collects α where type Elem α :: empty :: α insert :: Elem α α α... instance Eq (Elem [ε]) Collects [ε] where type Elem [ε] = ε empty = [] insert e xs = (e : xs)... [25..40]

Implementáció: nézetminták {-# LANGUAGE ViewPatterns #-} type Typ =... data TypView = Unit Arrow Typ Typ view :: Typ TypView view =... size :: Typ Integer size t = case (view t) of Unit 1 Arrow t 1 t 2 size t 1 + size t 2 Nézetminták segítségével pedig: size (view Unit) = 1 size (view Arrow t 1 t 2 ) = size t 1 + size t 2 [26..40]

Implementáció: mohón kiértékelt adatkonstruktorok data T = T!Int!Int A konstruktor! segítségével megjelölt paramétereit (strictness annotation) normálformára kell hozni, mielőtt azt alkalmazzuk. Körültekintéssel kell alkalmazni, mivel ez automatikusan nem vezet a teljesítmény növekedéséhez. Sőt, ronthatja a teljesítményt: ha az adott mezőt már egyszer kiértékeltük, akkor lényegében még egyszer kiértékeltetjük (feleslegesen). A helyzet tisztázásában a fordító nem mindig tud a segítségünkre lenni. [27..40]

Implementáció: egymásba ágyazott típusok -- alternáló lista data AList α β = Nil Cons α (AList β α) alist :: AList Int Char alist = Cons 1 (Cons A (Cons 2 (Cons B Nil))) -- ciklikus lista data Void data CList α β = Var β Nil RCons α (CList (Maybe β)) 1 2 clist 1, clist 2 :: CList Int Void 1 2 3 clist 1 = RCons 1 (RCons 2 (Var Nothing)) clist 2 = RCons 1 (RCons 2 (RCons 3 (Var (Just Nothing)))) A rekurzív részben az adattípust nem a deklaráció szerint alkalmazzuk: nested, non-regular, non-uniform, heterogenous data type Adattípusokon belüli invariánsok (típusozott) megtartására alkalmazható. [28..40]

FingerTree: definíció (1) class (Monoid (Measure α)) Measured α where type Measure α measure :: α Measure α data FingerTree α = Empty Single α Deep!(Measure α)!(digit α) (FingerTree (Node α))!(digit α) deep :: (Measured α) Digit α FingerTree (Node α) Digit α FingerTree α deep pr m sf = Deep (measure pr measure m measure sf ) pr m sf data Node α = Node2 (Measure α) α α Node3 (Measure α) α α α node2 :: (Measured α) α α Node α node2 x y = Node2 (measure x measure y) x y node3 :: (Measured α) α α α Node α node3 x y z = Node3 (measure x measure y measure z) x y z [29..40]

FingerTree: definíció (2) newtype Digit α = D { und :: [α] } prependdigit :: α Digit α Digit α prependdigit x (D xs) = D (x : xs) appenddigit :: Digit α α Digit α appenddigit (D xs) x = D (xs ++ [x]) breakdigit :: Digit α (α, Digit α) breakdigit (D (x : xs)) = (x, D xs) kaerbdigit :: Digit α (α, Digit α) kaerbdigit (D xs) = (last xs, D (init xs)) [30..40]

FingerTree: definíció (3) instance (Measured α) Measured (Node α) where type Measure (Node α) = Measure α measure (Node2 m ) = m measure (Node3 m _) = m instance (Measured α) Measured (Digit α) where type Measure (Digit α) = Measure α measure (D xs) = foldr ( ) mempty (map measure xs) instance (Measured α) Measured (FingerTree α) where type Measure (FingerTree α) = Measure α measure Empty = mempty measure (Single x) = measure x measure (Deep m _) = m [31..40]

FingerTree: létrehozás -- O(1) empty :: (Measured α) FingerTree α empty = Empty singleton :: (Measured α) α FingerTree α singleton = Single infixr 5 ( ) :: (Measured α) α FingerTree α FingerTree α x Empty = Single x x (Single y) = deep (D [x]) Empty (D [y]) x (Deep _ (D [y, z, u, w]) m sf ) = deep (D [x, y]) (node3 z u w m) sf x (Deep _ pr m sf ) = deep (prependdigit x pr) m sf -- O(n) ( ) :: (Measured α) [α] FingerTree α FingerTree α xs ys = foldr ( ) ys xs fromlist :: (Measured α) [α] FingerTree α fromlist xs = xs Empty digittotree :: (Measured α) Digit α FingerTree α digittotree (D xs) = fromlist xs [32..40]

FingerTree: elérés infixr 5 data ViewL α = EmptyL α (FingerTree α) -- O(1) viewl :: (Measured α) FingerTree α ViewL α viewl Empty = EmptyL viewl (Single x) = x Empty viewl (Deep _ pr m sf ) = p (deepl lpr m sf ) where (p, lpr) = breakdigit pr deepl :: (Measured α) Digit α FingerTree (Node α) Digit α FingerTree α deepl (D []) (viewl EmptyL) sf = digittotree sf deepl (D []) (viewl x m) sf = deep (nodetodigit x) m sf deepl pr m sf = deep pr m sf nodetodigit :: (Measured α) Node α Digit α nodetodigit (Node2 _ x y) = D [x, y] nodetodigit (Node3 _ x y z) = D [x, y, z] [33..40]

FingerTree: elérés (alkalmazás) isempty :: (Measured α) FingerTree α Bool isempty (viewl EmptyL) = True isempty _ = False headl :: (Measured α) FingerTree α α headl (viewl x _) = x taill :: (Measured α) FingerTree α FingerTree α taill (viewl _ x) = x [34..40]

FingerTree: összekapcsolás infixr 5 -- O(log(min(n, m))) ( ) :: (Measured α) FingerTree α FingerTree α FingerTree α xs ys = f xs [] ys where f :: (Measured α) FingerTree α [α] FingerTree α FingerTree α f Empty ts xs = ts xs f xs ts Empty = xs ts f (Single x) ts xs = x (ts xs) f xs ts (Single x) = (xs ts) x f (Deep _ pr 1 m 1 sf 1 ) ts (Deep _ pr 2 m 2 sf 2 ) = deep pr 1 (f m 1 (nodes (und sf 1 ++ ts ++ und pr 2 )) m 2 ) sf 2 nodes :: (Measured α) [α] [Node α] nodes [x, y] = [node2 x y] nodes [x, y, z] = [node3 x y z] nodes [x, y, z, u] = [node2 x y, node2 z u] nodes (x : y : z : xs) = node3 x y z : nodes xs [35..40]

FingerTree: felbontás (1) data Split φ α = Split (φ α) α (φ α) i: kezdőérték, P( ): monoton predikátum, csak és P(i) P(i d ) = let Split l x r = splitdigit p i d in tolist l ++ [x] ++ tolist r = tolist d P(i l ) P(i l x ) splitdigit :: (Measured α) (Measure α Bool) Measure α Digit α Split Digit α splitdigit p i (breakdigit (x, D [])) = Split (D []) x (D []) splitdigit p i (breakdigit (x, xs)) p j = Split (D []) x xs otherwise = let Split l y r = splitdigit p j xs in Split (prependdigit x l) y r where j = i measure x x i-1 x i x 1 x 2 x i+1 x n-1 vn-1... P... P x n i v 1 v 2 v i-1 v i [36..40] vn

FingerTree: felbontás (2) P(i) P(i t ) = let Split l x r = splittree p i t in tolist l ++ [x] ++ tolist r = tolist t P(i l ) P(i l x ) -- O(log(min(n l, n r ))) splittree :: (Measured α) (Measure α Bool) Measure α FingerTree α Split FingerTree α splittree p i (Single x) = Split Empty x Empty splittree p i (Deep _ pr m sf ) p vpr = let Split l x r = splitdigit p i pr in Split (digittotree l) x (deepl r m sf ) p vm = let Split ml xs mr = splittree p vpr m Split l x r = splitdigit p (vpr measure ml) (nodetodigit xs) in Split (deepr pr ml l) x (deepl r mr sf ) otherwise = let Split l x r = splitdigit p vm sf in Split (deepr pr m l) x (digittotree r) where (vpr, vm) = (i measure pr, vpr measure m) [37..40]

FingerTree: felbontás (3) t Empty = let Split l x r = splittree p i t in tolist l ++ [x] ++ tolist r = tolist t (l = Empty P(i l )) (r = Empty P(i l x )) split :: (Measured α) (Measure α Bool) FingerTree α (FingerTree α, FingerTree α) split p Empty = (Empty, Empty) split p t p (measure t) = (l, x r) otherwise = (t, Empty) where Split l x r = splittree p mempty t [38..40]

FingerTree: véletlen elérésű sorozatok (alkalmazás) newtype Elem ν α = Elem { getelem :: α } newtype Size = Size { getsize :: Int } deriving (Eq, Ord) newtype Seq α = Seq (FingerTree (Elem Size α)) instance Monoid Size where mempty = Size 0 mappend (Size m) (Size n) = Size (m + n) instance Measured (Elem Size α) where type Measure (Elem Size a) = Size measure (Elem _) = Size 1 fromlist :: [α] Seq α fromlist xs = Seq (FT.fromList (map Elem xs)) tolist :: Seq α [α] tolist (Seq t) = map getelem (FT.toList t) [39..40]

FingerTree: véletlen elérésű sorozatok (alkalmazás) length :: Seq α Int length (Seq xs) = getsize (FT.measure xs) splitat :: Int Seq α (Seq α, Seq α) splitat i (Seq xs) = (Seq l, Seq r) where (l, r) = FT.split (Size i <) xs (!) :: Seq α Int α (Seq xs)! i = getelem x where Split _ x _ = FT.splitTree (Size i <) (Size 0) xs [40..40]