1 / 34

Ievads funkcionālajā programmēšanā

Ievads funkcionālajā programmēšanā. Datorzinātnes pamati. Programmēšanas veidi (paradigmas): 1.

lynne
Download Presentation

Ievads funkcionālajā programmēšanā

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Ievads funkcionālajā programmēšanā Datorzinātnes pamati

  2. Programmēšanas veidi (paradigmas): 1 Imperatīvā programmēšana (PASCAL, BASIC, C, C++, ADA, FORTRAN, u.c.):Vēsturiski pirmais programmēšanas veids, imitē datora kā fiziskas iekārtas piedāvāto abstraktās mašīnas modeli. Mainīgā jēdziens, iespēja mainīt mainīgā vērtību programmas izpildes gaitā – analogs datora atmiņas šūnas jēdzienam. Piešķiršanas operators. Viens centrālais procesors secīgi izpilda instrukcijas. Programmas semantika – dabiski skaidrota kā instrukciju virkne. Funkcionālā programmēšana: Ideja – programma ir funkcija, programmas izpilde – funkcijas pielietošana argumentam. Mainīgie – analoģiski kā matemātikā – var glabāt patvaļīgu, bet fiksētu vērtību. Nav piešķiršanas operatora. Virknes kompozīcijas vietā – funkciju kompozīcija, ciklu vietā – rekursija (“tīrās” funkcionālās programmās). Iespējamas funkcijas, kuru argumenti un rezultāti arī ir funkcijas (augstākas kārtas funkcijas). Funkcionālā programmēšana – valoda LISP 1960. gadā, tālāk krietni attīstījusies:pieejamas valodas ar datu tipiem, strukturētām programmu uzdošanas iespējām : ML, HASKELL, MIRANDA. Aplūkosim tuvāk valodu ML.

  3. Programmēšanas veidi (paradigmas): 2 Loģiskā programmēšana: PROLOG: Programma – zināšanu bāze, apgalvojumi par to, kas ir zināms par problēmu apgabalu, kas ietver ziņas par iegūstamo rezultātu. Programmas izsaukums – mērķa predikāts. Programmai jānoskaidro, vai mērķa predikāta patiesumu var izvest no pieejamās zināšanu bāzes. Ja mērķa predikāts satur mainīgos, programma atrod mainīgo vērtības, ar kurām mērķa predikāts kļūst patiess. Valoda PROLOG – “tīrā” loģiskā programmēšana, plus risinājuma meklēšanas vadības direktīvas. Objektorientētā programmēšana: SIMULA, SMALLTALK, C++, JAVA, EIFFEL, u.c. Programma kā aktīvu objektu kopums. Katram objektam atribūti un metodes, publiskā un privātā daļa. Objekta tips – klase, iespējamas klašu hierarhijas, mantošana. Viens no praktiski visnozīmīgākajām programmēšanas veidiem. Paralēlā programmēšana: Paralēli programmu izpildes pavedieni. Kopēja atmiņas izmantošana, ziņojumu apmaiņa (sinhronizācija, u.c.) Vizuālā programmēšana: vizuālie objekti un to klases, datu ievads caur formām, procedūru izpilde, reaģējot uz notikumiem.

  4. Funkcionālā programmēšana: raksturojums Funkcionālā programmēšanas stila raksturojums (funkcionālā programmēšana “tīrā formā”): • Programma ir funkcija, kas ieejas datus attēlo par izejas datiem. Programmas izpilde – funkcijas pielietošana argumentiem. • Visas procedūras un funkcijas skaidri nodala ienākošās vērtības (argumentus) no izejošajām vērtībām (rezultātiem). • Netiek izmantoti mainīgā (kā atmiņas šūnai piesaistīta vārda) un piešķiršanas operatora jēdzieni – mainīgie tiek aizstāti ar parametriem. • Netiek izmantoti cikli – cikli ir aizstāti ar rekursīviem izsaukumiem. • Funkcijas vērtība ir atkarīga tikai no tās parametru vērtības, un nevis no funkcijas aprēķināšanas kārtības, vai arī no izpildes ceļa, kas novedis līdz šīs funkcijas izsaukumam. • Funkcijas ir pilnvērtīgas (“pirmās šķiras”) vērtības, valodas izteiksmēs lietojamas tāpat kā jebkādas citas vērtības. Funkcionālās valodās ir pieejamas arī īpašības, kas atkāpjas no šī stila. Funkcionālās programmēšanas būtiskās iezīmes: • Funkciju kompozīcija kā būtisks strukturizācijas līdzeklis • Vispārīgas (augstākas kārtas) funkcijas, kuru argumenti arī ir funkcijas • Aizturētās izpildes paradigma (daļā valodu) – iespējas darbības definēt bezgalīgu objektu līmenī (kā matemātiskā notācijā).

  5. Funkcionālā programmēšana: ieskats vēsturē Funkcionālās programmēšanas sākums: Lambda – rēķini, matemātiska sistēma funkciju uzdošanai un aprēķināšanai, 1935. gads. l - termi: M ::= x | lx.M | M N x - mainīgaislx.M - abstrakcija (funkcija x  M, parasti M = M(x)) M N - aplikācija: terms - funkcija M tiek pielietots argumenta termam N Piemērs: funkciju x  x2 apzīmē kā lx.x2 [x2 var tikt ieviests] Fakts. Lambda – rēķinos var aprakstīt tās un tikai tās funkcijas, kas ir izrēķināmas ar Tjūringa mašīnu. Plašāka informācija – nākamajā lekcijā. Funkcionālās programmēšanas valoda LISP, John McCarthy, 1958.g.: Programmas, dati tiek uzdoti kā saraksti. Vērtības, kas ir funkcijas, ir tikpat plaši lietojamas, kā jebkura cita vērtība. Pielietojumi AI sfērā. LISP – Lots of Silly Parentheses Common Lisp – populāra LISP vide SCHEME – vienkāršāka implementācija, apskatīsim nākamajā lekcijā.

  6. Valoda ML: ievads Valodai ML - interaktīva, interpretatīva vide. Piemēri: New Jersey SML vidē - 3 + 5;val it = 8 : int - ML sistēma kā atbildi uz lietotāja ievadu paziņo definētās vērtības tipu. - Izteiksmes tipu ML sistēma cenšas noteikt automātiski - Stingra tipu sistēma: katrai vērtībai, katrai izteiksmei savs tips. - Iebūvētie tipi: int, real, bool, unit, string, char - val x=3.5*6.0; val – vērtības deklarācijaval x = 21.0 : real - val y = x*x; Definētu vērtību var izmantot jaunās definīcijāsval y = 441.0 : real - fun sq n = n*n; fun – funkcijas deklarācijaval sq = fn : int -> int Funkcijas tips – sastāv no argumenta un rezultāta tipiem, ievietojam simbolu ->. val sq = fn – norāde, ka definētā vērtība ir funkcija. Funkciju pēc tās deklarācijas var izmantot izteiksmēs – pielietot argumentiem: - sq 5; val it = 25 : int

  7. Valoda ML: ievads (2) - fun sq n = n*n; fun – funkcijas deklarācijaval sq = fn : int -> int - sq 5; val it = 25 : int fun sq n = n*n : Tips ir neviennozīmīgs, SML NJ vide to uztvēra kā fn : int -> int, citas ML vides var ziņot par kļūdu. Iemesls: *, tāpat kā + ir “pārslogotas” (overloaded) funkcijas, kas pielietojamas gan int, gan arī real tipa vērtībām. ML vide nevar pēc dotās izteiksmes un tajā ieejošajiem operatoriem tipu noteikt viennozīmīgi. - fun sqq x = x * x : real; Konkrēti specificēts argumenta tipsval sqq = fn : real -> real - fun sqz x: real = x * x; Cits variants, kā specificēt argumenta tipu.val sqz = fn : real -> real Lai ML sistēma konstatēt (izvest) izteiksmes tipu, viņai par to var “signalizēt” dažādos veidos.

  8. Valoda ML: ievads (3) - sq 5; val it = 25 : int - sqq 5.0; val it = 25.0 : real - sqq 5; (… tycon mismatch …) Stingra tipu sistēma: nevar izteiksmēs int un real tipus likt vienu otra vietā. Ja nepieciešams operāciju ar real parametru pielietot int tipa argumentam, jāveic atklāta tipu konversija: - sqq (real 5);val it = 25.0 : real - fun s x = x + 1; Iespējams ekvivalents pieraksts: - val s = fn x => x + 1; val s = fn int -> int Cits veids, kā definēt funkciju, atbilst -termam x.x+1 Funkcija – arī vērtība, funkciju var pierakstīt arī val notācijā (s funkcija). fun – īpaša notācija, atvieglo funkciju uzdošanu. - s 43; val it = 44 : int

  9. Valoda ML: izteiksmes Izteiksmes valodā ML: operācijas un precedence: 1) ~ (unārais -), not2) *, /, div, mod3) +, -4) =, <, >, <>, <=, >= 5) andalso, orelse - aprēķina vispirms kreiso pusi, tad, ja nepieciešams, rēķina arī labo (saīsinātā aprēķināšana) - 14 div 3; val it = 4: int Veselo skaitļu dalīšana - 14 mod 3; val it = 2: int Atlikums dalīšanā - 14.0 / 3.0; val it = 4.66666666667: real - (14.0 / 3.0) * 3.0; val it = 14.0: real - 2 * 2 = 5; val it = false: bool - 3 = 2 andalso 2 div 0 = 5; val it = false : bool - 2 div 0 = 5 andalso 3 = 2; … divide by zero … - fun abs x = if x >= 0 then x else ~x; val abs = fn : int -> int if operatora piemērs valodas ML izteiksmes ietvaros

  10. Valoda ML: tipi char, string, unit Tips char; char tipa konstantes: #”a” Funkcijas:ord:char -> int,chr:int -> char, str:char -> string size:string -> int,explode:string -> char list,implode, … - fun hello {} = "hello";val hello = fn : unit -> string unit - tukšais (viena elementa) tips, satur tikai (), atbilst C tipam void. Valodā ML katrā tipā jābūt vismaz vienam elementam. - hello; val it = fn : unit -> string - hello ();val it = “hello” : string Funkcijas pielietošana unit tipa argumentam. - "Hello " ^ "world!"; Simbolu virkņu konkatenācijaval it = "Hello world!": string

  11. Valoda ML: lokālie mainīgie funkcijās Lokālās deklarācijas:fun area(a,b,c) = let val p=(a+b+c)/2.0 in Math.sqrt(p*(p-a)*(p-b)*(p-c)) end; val area = fn: real * real * real -> real area(3.0,4.0,5.0);val it = 6.0: real -- taisnleņķa trijstūris piemērā Trīsstūra laukuma aprēķināšanas formula, lokālā deklarācija saīsina izteiksmes pierakstu, var uzlabot lasāmību. Mainīgā (simbola) p vērtība izteiksmes aprēķināšanas gaitā tiek aprēķināta tikai vienreiz. Iespējams let izteiksmēs definēt arī vairākus mainīgos: let val x = 3 val y = x * x in x * y end;val it = 27: int val x = 4;val x = 4: int let val x = 3 and y = x * x in x * y end;val it = 48: int Lokālās vērtības deklarācijas, kas atdalītas ar “and” tiek aprēķinātas visas reizē, izmantojot tās mainīgo vērtības, kas bija spēkā let komandas izpildes sākuma brīdī.

  12. Valoda ML: bibliotēkas un i/o Lokālās deklarācijas:fun area(a,b,c) = let val p=(a+b+c)/2.0 in Math.sqrt(p*(p-a)*(p-b)*(p-c)) end; Bibliotēku atvēršana:- open Math;atver Math bibliotēku, var rakstīt vienkāršisqrt ML vides atbilde: uzskaitīt bibliotēkā Math pieejamos datu tipus, kā arī pieejamo vērtību un funkciju tipus. Bibliotēka – definē struktūru (ML jēdziens bibliotēkas vienuma apzīmēšanai) ML sistēmā piedāvātas bibliotēkas:Bool, Byte, Char, Int, Real, String, StringCvt, Word, u.c. Failu apstrādes bibliotēka: TextIO, piedāvā funkcijas inputLine un output: open TextIO; output(stdOut, inputLine(stdIn)); Tipu konversija: Int.toString: int -> string, Int.fromString: string -> int option(sk. datu tipus: datatype ‘a myoption = NONE | SOME of ‘a; ) Analoģiski Bool tipam.

  13. Valoda ML: praktiski ieteikumi Darbs ar ārējiem programmu tekstiem:- use “area.sml”; Definīciju ielasīšana- OS.FileSys.getDir (); Aktīvās direktorijas nosaukums- OS.FileSys.chDir (); Fails “chdir.sml” (piemēram):fun chdir s = OS.FileSys.chDir(OS.FileSys.getDir() ^ "\\" ^ s)fun cdsml () = OS.FileSys.chDir "C:\\sml”fun cdbin () = OS.FileSys.chDir "C:\\sml\\bin”fun dname () = OS.FileSys.getDir () Piezīme: var izpildīt arī komandu open OS.Filesys; Termu izdrukas dziļums: Compiler.Control.Print.printDepth := 100; Termu izdrukas garums: Compiler.Control.Print.printLength := 1000; Kompilatora parametri: open Compiler.Control.Print;

  14. Valoda ML: reālie skaitļi > 1 = 1;val it = true : bool; > 2.1 = 2.1;Error: operator and operand don’t agree [equality type required] Valodā ML: vienādība nav definēta reāliem skaitļiem un funkcijām. Valodā HASKELL šis jautājums atrisināts. > Open Real; > 2.1 < 2.1;val it = false : bool; > 2.1 < 2.11;val it = true : bool; Pieejamas funkcijas: floor, ceil, trunc, round, toString, u.c. Skatīt arī bibliotēku IEEEReal.

  15. ML: rekursija, un šabloni Faktoriāla aprēķināšanas funkcija: fun fac n = if n=0 then 1 else n * fac(n-1);val fac = fn: int -> int Rekursīvs izsaukums, fac n aprēķināšanai izsauc fac ar argumenta vērtību n-1. Alternatīvs funkcijas definīcijas variants, izmanto šablonu atbilstību: fun fac1 0 = 1 | fac1 n = n * fac1(n-1);val fac1 = fn: int -> int Šabloni var pārklāties (neatkarīgi no prezentācijas veida), izpildes laikā paņems pirmo, kas atbilst. Ja šablons nepilnīgs - brīdinājums funkcijas definēšanas laikā, ja izsaukums ar nedefinētu vērtību – programma apstājas ar kļūdas situāciju. fun gcd x y = if x = y then x else if x>y then gcd(x-y,y) else gcd(x,y-x);val gcd = fn: int -> int -> int

  16. ML: izņēmuma situācijas fun fac n = if n=0 then 1 else n * fac(n-1); fun fac1 0 = 1 | fac1 n = n * fac1(n-1); fac 6;val it = 720: int fac 13;(… overflow …) fac ~1;ieciklošanās exception facE; Lietotāja definēta izņēmuma situācija fun fac2 n = if n < 0 then raise facE else if n = 0 then 1 else n * fac2(n-1); fun fac3 n = if n < 0 then raise facE else (case n of 0 => 1 | n => n * fac3(n-1)); Ilustrēta arī case notācija izteiksmju veidošanā.

  17. ML: pāri, korteži, polimorfisms (3,5) : int * int (3, true) : int * bool - fun divide(i, j) = (i div j, i mod j);> val divide = fn : (int * int) -> (int * int) - fun max(x,y) : int = if x < y then y else x;> val max = fn : (int*int)->int - fun fst(x,y) = x; > val fst = fn : (‘a * ‘b) -> ‘a - fun snd(x,y) = y;> val snd = fn : (‘a * ‘b) -> ‘b ‘a, ‘b - tipu mainīgie, pārus var veidot no dažādu tipu objektiem, funkcijas fst un snd var pielietot visiem pāriem; Viens un tas pats mainīgais vienā tipu izteiksmē visās vietās apzīmē vienu un to pašu tipu. (1,3,5) : int * int * int Kortežs garumā 3, funkciju fst pielietot nevar- fst (1,3,5);… failure (tycon …) …

  18. Vairāku argumentu funkcijas 2 iespējas, kā definēt skaitļu saskaitīšanu: - fun plus(a,b):int = a + b;> val plus = fn : int * int -> int - fun add a b = a + b: int;> val add = fn : int -> int -> int Funkcijai plus vienmēr vajag uzreiz abus “argumentus” (vienu argumentu, kas ir abu skaitļu pāris) Funkcija add var argumentus apstrādāt secīgi, vienu pēc otra, šis ir parastais variants int -> int -> intnozīmēint -> (int -> int) Funkcija, kas veselam skaitlim piekārto int -> int funkciju - val succ = add 1;funkciju add pielietojam tikai vienam argumentam …> val succ = fn : int -> int - succ 6;> val it = 7:int

  19. Augstākas kārtas funkcijas Funkcija, kuras viens no argumentiem ir funkcija: - fun compose2 f x = f(f x); > val compose2 = fn :(‘a -> ‘a) -> ‘a -> ‘a - fun sq x = x * x: int; > val sq = fn : int -> int; Funkcijai compose2 pirmais arguments ir funkcija ar tipu (‘a -> ‘a) Funkcija compose2 pielietota tikai vienam argumentam - funkcijai sq: - val power4 = compose2 sq; > val power4 = fn : int -> int; Funkcija compose2 – funkcija ar 2 argumentiem. Iespējams to pielietot vienam argumentam, rezultāts – funkcija, kas gatava pieņemt otru argumentu. compose2 sq aprēķināšanas rezultātā iegūto funkciju power4 var pielietot tālāk: - power4 3; > val it = 81 : int

  20. Vairāku argumentu funkcijas: papildmateriāls - fun plus(a,b):int = a + b; > val plus = fn : int * int -> int - fun add a b = a + b: int; > val add = fn : int -> int -> int Funkcijai plus vienmēr vajag uzreiz abus “argumentus”, bet funkcija add var argumentus apstrādāt secīgi, vienu pēc otra. Ja funkcija add pielietota vienam argumentam, rezultāts – joprojām funkcija, kas gatava pieņemt otru argumentu. Curry - Howard izomorfisms (“abi veidi ir vienlīdz iespējami”) - fun curry f x y = f (x,y); > val curry = fn : (‘a * ‘b -> ‘c) -> (‘a -> ‘b -> ‘c) - fun uncurry f (x,y) = f x y; > val uncurry = fn : (‘a -> ‘b -> ‘c) -> (‘a * ‘b -> ‘c) - val add = curry plus; Šāda ir alternatīva iespējama definīcija funkcijai add. Piezīme: tipu informāciju ML vide bija spējīga ģenerēt automātiski.

  21. Saraksti valodā ML - nil;sinonīms ar - [], tukšais saraksts> val it = [] : ‘a list - 3 :: []; saraksta konstruktors – elementa pievienošana sarakstam> val it = [3] : int list - 5 :: [3]; vēl viena elementa pievienošana> val it = [5,3] : int list rezultāts izteikts saraksta saīsinātajā formā - val x = 11 :: [5,3]; > val x = [11,5,3] : int list - fun len nil = 0 | len (a :: s) = len s + 1; Funkcijas definīcija, izmantojot šablonu atbilstību> val len = fn : ‘a list -> int - fun len nil = 0 | Var definēt arī šādi len (_ :: s) = len s + 1; _ vietā var būt jebkāds elements> val len = fn : ‘a list -> int - fun sumlist nil = 0 | sumlist (a :: s) = a + sumlist s;> val sumlist = fn : int list -> int

  22. Saraksti valodā ML: turpināts Sarakstu apstrādē var tikt izmantotas funkcijas hd un tl, kas pēc dota saraksta atdod attiecīgi saraksta pirmo elementu un visu pārējo sarakstu bez pirmā elementa. Varam definēt: fun hd (a::_)=a;> val hd = fn: ‘a list -> ‘a Sistēma izdos arī brīdinājumu: Match not exhaustive Izpildes laikā, ja mēģinās izpildīt hd [] – izpildes laika kļūda Labāka definīcija: izmantot izņēmuma situācijas: - exception hd and tl;> exception hd > exception tl - fun hd nil = raise hd | hd (a::_)=a;> val hd = fn: ‘a list -> ‘a - fun tl nil = raise tl | tl (_::s)=s;> val tl = fn : ‘a list -> ‘a list > hd nil; ( Failure: hd )

  23. Saraksti valodā ML: append un reverse fun append nil l = l | append (h::t) l = h :: (append t l); append [1,2,3] [4,5] -> 1 :: append [2,3] [4,5] ->1 :: (2 :: append [3] [4,5]) ->1 :: (2 :: (3 :: append [] [4,5]) ->1 :: (2 :: (3 :: [4,5])  [1,2,3,4,5] fun reverse nil = nil | reverse (h::t) = append (reverse t) [h]; reverse [1,2,3,4] ->append (reverse [2,3,4]) [1] ->append (append (reverse [3,4]) [2]) [1] ->append (append (append (reverse [4]) [3]) [2]) [1] ->append (append (append (append (reverse [])[4])[3])[2]) [1] ->append (append (append (append [] [4]) [3]) [2]) [1] ->append (append (append [4] [3]) [2]) [1] -> … ->append (append [4,3] [2]) [1] -> … -> append [4,3,2] [1] -> … -> [4,3,2,1] … Kvadrātiska sarežģītība … fun rev2 (nil,acc) = (nil,acc) | rev2 ((h::t),acc) = rev2 (t,(h::acc));Labāks! fun rev1 x = snd(rev2(x,nil)); Darbojas lineārā laikā

  24. Saraksti valodā ML: tālāki piemēri fun listgen 0 = [0] | listgen n = n :: listgen (n-1); Testa piemēru iegūšana fun map f nil = nil | map f (h::t) = (f h):: (map f t); map funkcija – pielieto argumenta funkciju f katram argumenta saraksta elementam - map sq [1,2,3,4];> val [1,4,9,16] : int list fun reduce f nil a = a | reduce f (h::t) a = reduce f t (f h a); reduce: atkārtoti izpilda divargumentu funkciju f, sākot no vērtības a, pēc kārtas ar f piesaistot visus saraksta elementus. fun add x y = x + y; fun mult x y = x * y; fun addelems xlist = reduce add xlist 0; Funkcijas addelems definīcija addelems [1,2,3,4] -> 10 fun multelems xlist = reduce mult xlist 1;

  25. Saraksti valodā ML: tālāki piemēri (2) fun reduce f nil a = a | reduce f (h::t) a = reduce f t (f h a); fun add x y = x + y; fun mult x y = x * y; fun addelems xlist = reduce add xlist 0; Funkcijas addelems definīcija addelems [1,2,3,4] -> 10 Alternatīva funkcijas reduce definīcija (cita argumentu secība): fun reduce1 f a nil = a | reduce1 f a (h::t) = reduce1 f (f h a) t; Varam definēt funkcijas addelems, multelems kā vērtības: val addelems = reduce1 add 0; val multelems = reduce1 mult 1;

  26. Saraksti valodā ML: kārtošana Kārtošana, izmantojot ievietošanu (insertion sort) fun insert x nil = [x] | insert x (h::t) = if x < h then (x::(h::t)) else (h::(insert x t)); fun insert_sort nil = nil | insert_sort (h::t) = insert h (insert_sort t); Visa programma izveidota 4 rindiņās. Vai C var uzrakstīt tik vienkāršu kārtošanas programmu? Darbojas laikā, kas proporcionāls n2.

  27. Saraksti valodā ML: merge sort Kārtošana, izmantojot saliešanu (merge sort) fun merge nil x = x | merge x nil = x | merge (a :: al) (b :: bl) = if a < b then (a :: (merge al (b :: bl))) else (b :: (merge (a::al) bl)); fun split nil = (nil, nil) | split (h :: nil) = ([h], nil) | split (h :: (g :: ls)) = let val (a,b) = split ls in (h :: a, g :: b) end; fun merge_sort nil = nil | merge_sort [a] = [a] | merge_sort x = let val (e,f) = split x; val a = merge_sort e; val b = merge_sort f in merge a b end; Ievērojam šablonu atbilstības izmantošanu lokālajās deklarācijās – let izteiksmēs funkciju split un merge_sort definīcijā. Darbojas laikā n * log n. Testa piemēri: merge_sort (listgenx 10000), insert_sort (listgenx 10000) fun x_next n = (n + 17) mod 1000; fun listgenx 0 = [0] | listgenx n = let val a = listgenx (n-1) in (x_next (hd a)) :: a end;

  28. i_vertex(  , 17 ,  ) i_vertex(  , 4 ,  ) leaf(13) leaf(3) leaf(5) Konstruktīvie (induktīvie) datu tipi datatype color = red | green | blue | yellow; fun rotate red = green | rotate green = blue | rotate blue = yellow | rotate yellow = red; datatype btree = leaf of int | i_vertex of btree * int * btree; fun listel (leaf (x)) = [x] | listel (i_vertex (t1,a,t2)) =(listel t1) @ (a ::(listel t2)) val t_1 = i_vertex(i_vertex(leaf(3),4,leaf(5)),17,leaf(13)); val t_2 = i_vertex(t_1,15,t_1); listel t_1; ( [3,4,5,17,13] ) listel t_2; ( ??? ) datatype btl = ll of int list |ii of btl * btl * int list fun conlists = ??? fun count11 = ???

  29. Konstruktīvie (induktīvie) datu tipi (turpināts) Binārais koks ar 0, 1 vai 2 bērniem, katrā lapā vai iekšējā virsotnē pa 2 vārdiem: datatype b_s = l_s of string * string | v1_s of b_s * string * string | v2_s of b_s * b_s * string * string; Ja vārdi tikai lapās (analoģiski arī ar citiem objektiem): datatype b_sl = ll_s of string * string | vv1_s of b_sl | vv2_s of b_sl * b_sl; Binārs koks, kas var būt arī tukšs: datatype bb_t = empty | node of bb_t * bb_t * int; val my_tree = node (node (empty, node (empty, empty, ~3), 11), node (empty, empty,7), 13)

  30. Valodas IMP interpretators: izteiksmes (fun fst(x,y) = x; fun snd(x,y) = y;) datatype aexp = acon of int | var of string | plus of aexp * aexp | minus of aexp * aexp | times of aexp * aexp; datatype bexp = bcon of bool | eq of aexp * aexp | ge of aexp * aexp | not_b of bexp | and_b of bexp * bexp | or_b of bexp * bexp fun aval (acon(x)) s = x | aval (var(v)) s = s v |aval (plus(a, b)) s = (aval a s) + (aval b s) |aval (minus(a, b)) s = (aval a s) - (aval b s) |aval (times(a, b)) s = (aval a s) * (aval b s); fun bval (bcon x) s = x |bval (eq (a,b)) s = (aval a s = aval b s ) |bval (ge (a,b)) s = (aval a s >= aval b s ) |bval (not_b(b)) s = not ( bval b s ) |bval (and_b(b1,b2)) s = (bval b1 s) andalso (bval b2 s) |bval (or_b(b1,b2)) s = (bval b1 s) orelse (bval b2 s);

  31. Valodas IMP interpretators datatype com = skip | assign of string * aexp | seq of com*com | if_c of bexp * com * com | while_c of bexp * com; fun do_assign x a s y = if x=y then (aval a s) else (s y); > val do_assign = fn : string -> aexp -> (string -> int) -> (string -> int) fun eval (skip) s = s | eval (assign(x,a)) s = do_assign x a s |eval (seq(c1,c2)) s = eval c2 (eval c1 s) |eval (if_c(b,c1,c2)) s = if (bval b s) then (eval c1 s) else (eval c2 s) |eval (while_c(b,c)) s = if (bval b s) then (eval (while_c(b,c)) (eval c s)) else s; > val eval = fn : com -> (string -> int) -> (string -> int) Kā nokodēt piemēros string -> int ? …

  32. Valodas IMP interpretators: prezentācija fun mk_state nil x = 0 | mk_state ((v,val)::t) x = if v=x then val else mk_state t x; > val mk_state = fn : ('a * int) list -> 'a -> int val sigma = mk_state [("x",14),("y",21)];> val sigma = fn : string -> int fun show_value s x = (x,s(x)); fun show_state s l = map (show_value s) l; show_value sigma "x";> val it = ("x",14): string * int show_state sigma ["x","y","z"];> val it = [("x",14),("y",21),("z",0)] : (string * int) list fun run c s = show_state (eval c (mk_state s)) (map fst s); > val run= fn: com -> (string * int) list -> (string * int) list eval analogs, darbojas uz stāvokļiem kā pāru (mainīgais, vērtība) sarakstiem

  33. Valodas IMP interpretators: rezultāti fun run c l = show_state (eval c (mk_state l)) (map fst l); > val run= fn: com -> (string * int) list -> (string * int) list val gcd_program = let val ax = var("x"); val ay = var("y"); val b1 = not_b(eq(ax,ay)); val b2 = ge(ax,ay); val c1 = assign("x",minus(ax,ay)); val c2 = assign("y",minus(ay,ax)); val c3 = if_c(b2,c1,c2) in while_c(b1,c3) end; > val gcd_program = …… : com run gcd_program [("x",14),("y",35)]; > val it = [("x",7),("y",7)] : (string * int) list

  34. Operatori valodā ML Funkcijas valodā ML: var ņemt argumentus pēc kārtas, var prasīt visus argumentus reizē. (funkcijas, kas prasa visus argumentus pēc reizē var tikt uzskatītas par viena argumenta funkcijām). Operatori: infiksā notācijā attēloti simboli, apzīmē funkcijas, kas prasa visus argumentus reizē. Operatoru piemēri: > op + ; val it = fn : int * int -> int > op :: ; val it = ‘a * ‘a list -> ‘a list > op @ ; Sarakstu konkatenācija. val it = ‘a list * ‘a list -> ‘a list Pastāv arī iespējas lietotājam definēt jaunus operatorus.

More Related