34
Ievads funkcionālajā programmēšanā Datorzinātnes pamati

Ievads funkcionālajā programmēšanā

  • Upload
    lynne

  • View
    48

  • Download
    0

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: Ievads funkcionālajā programmēšanā

Ievads funkcionālajā programmēšanā

Datorzinātnes pamati

Page 2: Ievads funkcionālajā programmēšanā

Programmēšanas veidi (paradigmas): 1Imperatī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.

Page 3: Ievads funkcionālajā programmēšanā

Programmēšanas veidi (paradigmas): 2Loģ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.

Page 4: Ievads funkcionālajā programmēšanā

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ā).

Page 5: Ievads funkcionālajā programmēšanā

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.

- termi: M ::= x |x.M | M N x - mainīgais x.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ā x.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 ParenthesesCommon Lisp – populāra LISP videSCHEME – vienkāršāka implementācija, apskatīsim nākamajā lekcijā.

Page 6: Ievads funkcionālajā programmēšanā

Valoda ML: ievadsValodai 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ācija val 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ācija val 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

Page 7: Ievads funkcionālajā programmēšanā

Valoda ML: ievads (2)- fun sq n = n*n; fun – funkcijas deklarācija

val sq = fn : int -> int- sq 5;

val it = 25 : intfun 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.

Page 8: Ievads funkcionālajā programmēšanā

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 -> intCits veids, kā definēt funkciju, atbilst -termam x.x+1Funkcija – 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

Page 9: Ievads funkcionālajā programmēšanā

Valoda ML: izteiksmesIzteiksmes valodā ML: operācijas un precedence:

1) ~ (unārais -), not 2) *, /, div, mod 3) +, - 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

Page 10: Ievads funkcionālajā programmēšanā

Valoda ML: tipi char, string, unitTips 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

Page 11: Ievads funkcionālajā programmēšanā

Valoda ML: lokālie mainīgie funkcijāsLokā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 -> realarea(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: intval x = 4;

val x = 4: intlet val x = 3 and y = x * x in x * y end;

val it = 48: intLokā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ī.

Page 12: Ievads funkcionālajā programmēšanā

Valoda ML: bibliotēkas un i/oLokā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ši sqrt

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.

Page 13: Ievads funkcionālajā programmēšanā

Valoda ML: praktiski ieteikumiDarbs 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;

Page 14: Ievads funkcionālajā programmēšanā

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.

Page 15: Ievads funkcionālajā programmēšanā

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 elseif x>y then gcd(x-y,y) else gcd(x,y-x);val gcd = fn: int -> int -> int

Page 16: Ievads funkcionālajā programmēšanā

ML: izņēmuma situācijasfun 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: intfac 13;

(… overflow …)fac ~1;

ieciklošanāsexception facE; Lietotāja definēta izņēmuma situācijafun 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ā.

Page 17: Ievads funkcionālajā programmēšanā

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 …) …

Page 18: Ievads funkcionālajā programmēšanā

Vairāku argumentu funkcijas2 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 -> intFunkcijai 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 -> int nozī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

Page 19: Ievads funkcionālajā programmēšanā

Augstākas kārtas funkcijasFunkcija, 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

Page 20: Ievads funkcionālajā programmēšanā

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.

Page 21: Ievads funkcionālajā programmēšanā

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

Page 22: Ievads funkcionālajā programmēšanā

Saraksti valodā ML: turpinātsSarakstu 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 exhaustiveIzpildes laikā, ja mēģinās izpildīt hd [] – izpildes laika kļūdaLabā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 )

Page 23: Ievads funkcionālajā programmēšanā

Saraksti valodā ML: append un reversefun 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ā

Page 24: Ievads funkcionālajā programmēšanā

Saraksti valodā ML: tālāki piemērifun 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īcijaaddelems [1,2,3,4] -> 10fun multelems xlist = reduce mult xlist 1;

Page 25: Ievads funkcionālajā programmēšanā

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īcijaaddelems [1,2,3,4] -> 10Alternatī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;

Page 26: Ievads funkcionālajā programmēšanā

Saraksti valodā ML: kārtošanaKā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.

Page 27: Ievads funkcionālajā programmēšanā

Saraksti valodā ML: merge sortKā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;

Page 28: Ievads funkcionālajā programmēšanā

Konstruktīvie (induktīvie) datu tipidatatype 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 listfun conlists = ???fun count11 = ???

i_vertex( , 17 , )

i_vertex( , 4 , ) leaf(13)

leaf(3) leaf(5)

Page 29: Ievads funkcionālajā programmēšanā

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)

Page 30: Ievads funkcionālajā programmēšanā

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);

Page 31: Ievads funkcionālajā programmēšanā

Valodas IMP interpretatorsdatatype 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 ? …

Page 32: Ievads funkcionālajā programmēšanā

Valodas IMP interpretators: prezentācijafun 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

Page 33: Ievads funkcionālajā programmēšanā

Valodas IMP interpretators: rezultātifun 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

Page 34: Ievads funkcionālajā programmēšanā

Operatori valodā MLFunkcijas 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 listPastāv arī iespējas lietotājam definēt jaunus operatorus.