IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

1. diel - Úvod do funkcionálního programovania

V tomto tutoriále si ukážeme, čo je to funkcionálne programovanie, k čomu je dobré a ako ho plne využijeme.

Funkcionálne programovanie

Funkcionálne programovanie sa hodí najmä pre prácu s dátami, napr. Na štatistiky alebo analýzy a to je tiež doména funkcionálnych jazykov. Pre ich uplatnenie je dnes pomerne veľký trh, napr. Pre finančné spoločnosti (možno ste počuli pojem Big dáta). Často sa používajú aj na machine learning alebo spracovanie prirodzeného jazyka. Výrazne zjednodušujú paralelizmus, čo je jeden z dôvodov jeho úspechu. Pre tvorbu klasických programov sa ale spravidla funkcionálne programovanie mieša s "klasickým" záväznými programovaním.

Programovacie paradigmy

Aby sme funkcionálne programovanie pochopili čo najlepšie, pripomeňme si najprv ako funguje "klasické" programovanie a spomeňme si aj ďalšie konkurenčné programátorské paradigma.

Imperatívne programovanie

Najskôr sa ale pozrime, ako sa programuje "normálne". Jazyky ako C, Java, Python, C # a ďalšie sú skvelými ukážkami tzv. Imperatívny spôsobu programovania. V podstate hovoríme programe, čo má robiť. Ukážme si nejaký jednoduchý kód:

int [] pole = {1, 2, 3, 4, 5};

string spocti(int [] a) {
    int b = a.length;
    int c = b – 2;
    System.out.println(c - b);
    string s = "Hurrraaaaaaaaa, je to v kapse";
    return s;
}

Do premenné a si uložíme pole prvkov, ktoré funkcie dostane ako parameter. Do b si uložíme dĺžku a, do c si dosadíme b - 2, a potom vytlačíme výsledok. Parameter a značí objekt, ktorý má nejaké vlastnosti a jedným z nich je dĺžka. Opýtania sa na dĺžku je konštantná operácie, objekt, tu pole, si samo pamätá, ako je veľké, lebo ho vopred staticky inicializujeme čiže vopred počítaču povieme, ako ho má pripraviť.

Zatiaľ asi nič nové.

Deklaratívne programovanie

Pre určité typy úloh sa ale môže hodiť iný prístup. Tých máme dokonca viac. Jedným z nich je povedať počítači, ako vyzerá náš problém. Tomu sa hovorí deklaratívne programovanie, alebo niekedy tiež "logické programovanie". Proste popíšeme aký chceme výsledok, nie postup na jeho dosiahnutie, ten je už na počítači.

Ukážkou deklaratívneho jazyka je populárny SQL, kde nehovoríme ako má databázy interne dáta presne získať, ale len špecifikujeme aké dáta nás vo výsledku zaujímajú, ako majú byť zoradené, aké majú obsahovať stĺpce a podobne. Databáza to za nás potom už vymyslí a vnútorne našu požiadavku preloží na nejaké imperatívne cykly a podmienky. Od tých sme my ale plne odtienenie.

Deklaratívne programovanie však nie je obmedzené len na databázy. Najlepším nástrojom pre ukážku logického programovania je programovací jazyk Prolog, ktorého meno pochádza z Programing in logike. Logické programovanie pochádza z matematickej logiky, kedy z nejakého stavu možno jasne povedať, či platia alebo nie. A pokiaľ sa nedá dokázať, že platí, potom neplatí. Ako ukážku použijeme rodokmeň. Ten budeme brať ako nejakú databázu faktov az nich chceme získať výsledok:

matka(jana,tereza).
matka(jana,jitka).
matka(jitka,anna).
otec(jan,jitka).
otec(jiri,anna).

babicka(Kdo, Koho):-matka(Kdo,X), ( otec(X,Koho) ; matka(X,Koho) ).

Je jasné, že kód sa na prvý pohľad zdá len ako mágia, ale hneď to snáď bude jasnejšie. (;) A (,) sú symboly z logiky, kde (,) znamená and (a zároveň) a (;) označuje or (alebo). Zátvorky si predstavte ako čiernu krabičku ( "tu strčíme niečo dovnútra, tu vylezie výsledok"). Ak "strčíme" do zátvorky meno, program nám povie, či je niekto babičkou niekoho v tom danom systéme. Ak máme v databáze informácie o tom, že je Jána matka Jitky a Jitka matka Anny, potom musí byť Jána babička Anny.

napr:

?-babička(anna,bozena).
false.
?-babička(anna,X).
false.
?-babička(jana,X).
X=anna;

Vyššie sa pýtame na nasledujúce faktami:

  1. Je Anna babičkou Boženy? Výsledok je false.
  2. Čí babička je Anna? false (ničí)
  3. Čí babička je Jana? Anny

Ak by tam však táto informácia nebola, program tvrdenie poprie ako v prvom prípade. Aj keby ju tam len niekto zabudol napísať. Podobne ako v SQL tu totiž hovoríme, ako má výsledok vyzerať namiesto toho, ako presne ho vykutáme z dát. V SQL by dotaz na rodokmeň mohol vyzerať napr. Nasledovne:

SELECT vnucka FROM babicka-vnucka WHERE babicka = jana

To bol len príklad.

V logickom programovaní idú veľmi dobre riešiť stavové problémy, napr. Sudoku, hádanka Farmár, vlk, koza, kapusta a podobné ... Týmto sa však s logickým / deklaratívnym programovaním lúčime, logickému programovanie tento kurz nepatrí.

Funkcionálne programovanie

My totiž môžeme na programovanie nazerať ešte z inej strany. Predstavme si program ako jednu dlhú funkciu, ktorá niečo vezme na vstupe a vráti výsledok. Majme napr. Funkciu (plus), ktorá nám spočíta dve čísla a funkciu (převrať), ktorá prevráti číslo, teda z 21 nám urobí 12 atd ... Zložením funkcií nám vznikne funkcie magie(x,y) = prevrat.secti(x,y), ktorá vezme dve čísla, spočíta je a výsledok obráti. (Matematicky sa "vláčik" posúva sprava doľava). Funkcia magie(9,8) = 71, magie(4,5) = 9, magie(10,0) = 9 atď ...

Tento štýl sa v mnohom podobá logickému programovania, ale mnohonásobne ho predčí eleganciou a efektivitou. Chcime napr. Program, ktorý nám vráti v poli všetky deliteľa nejakého čísla:

dejMiDelitele n =  [ x | x <- [1 .. n] , n `mod` x == 0 ]

Jednoducho popíšeme, čo chceme robiť. Máme hornú hranicu a chceme všetky čísla od 1 do tej hranice, pre ktoré platí, že číslo modulo x je rovné 0, čiže x je deliteľom čísla n. Využitie funkcionálního programovania je teda jasné. Podobný kód s ním dokážeme písať oveľa efektívnejšie a to bez vedľajších efektov. Čo to znamená?

Imperatívne jazyky pracujú a sekundárne usadzovanie do premenných as manipuláciou s nimi. Či už premennú zmenšíme, zväčšíme, pošleme na zásobník, uložíme do poľa, vytlačíme atď., Pracujeme s pamäťou. To je nebezpečné a niekedy tiež zdĺhavé. Funkcionálne programovaní na to ide z druhej strany. Vyrobíme si "mašinku", do ktorej niečo vsunieme a na konci z nej vypadne výsledok. Vďaka tomu nemáme problém napr. S paralelizmem, proste dáme vedľa seba 3 mašinky, dáme do nich 3 vstupy a dostaneme 3 výstupy. A ak robíme Big dáta, určite ich chceme robiť paralelne, pretože by to inak trvalo naozaj dlho :)

Ďalej je tu iný spôsob písania programov. U funkcií chceme, aby na jasný vstup dala jasný výstup. To má za následok jednoduché ladenie programov, lebo pokiaľ každá funkcia robí to, čo má, pre daný výsledok je len okamihu pospája za seba. Druhým veľmi príjemným dôsledkom je, že skladáme za seba malé programy. Väčšinou sa zmestia do 10 riadok. Opäť, výsledok sa dostaví hneď, akonáhle vám začne vstup hádzať nečakaný výstup.

Vývojové prostredie

Teraz sa ešte zmienime o prostredí, ktoré budeme používať. Je to GHCi a nájdete ho ako pre Windows i Linux. Výhodou je jeho jednoduchosť. Aj keď nie ste na programovanie v konzole zvyknutí, napriek tomu odporúčam tento nástroj, pretože je to presná ukážka toho, čo by funkcionálne programovanie malo robiť. To, čo má, a ani o trochu naviac :) Napriek tomu nezúfajte. Okrem kompileru potrebujeme ešte textový editor, na ktorom budeme písať naše funkcie. Na to stačí poznámkový blok, na Linuxe je na to vhodný VIM, ktorý podporuje Haskell syntax, alebo veľa ďalších nástrojov.

Funkcionálne programovacie jazyky

Čo sa týka toho, čo je a čo nie je funkcionálne jazyk, je potrebné si ujasniť, čo od funkcionálního jazyka očakávame. Ak chceme, aby v ňom nešlo písať procedurálne, potom nám mnoho jazykov nezostane. Napríklad Haskell je čisto funkcionálne jazyk. Jazyky ako Dart, Scala, F # sú funkcionálne. Ak však definíciu rozšírime na to, či v jazyku možno písať funkcionálne, potom tam patrí jazyky ako C #, Java, Python atď ... Týmto jazykom sa preto hovorí často multiparadigmatické a v praxi je funkcionálne programovanie naozaj často s záväznými programovaním kombinované. Danú časť programu jednoducho napíšeme prístupom, ktorý je pre ňu efektívnejšie. Funkcionálne programovanie multiparadigmatické jazyky podporujú pomocou tzv. Lambda výrazov. K tomu sa však dostaneme.

Pokračovať budeme nabudúce v lekcii Prvá funkcia v Haskell .


 

Všetky články v sekcii
Haskell
Preskočiť článok
(neodporúčame)
Prvá funkcia v Haskell
Článok pre vás napísal Ondřej Michálek
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje teoretické informatice. Ve svých volných chvílích nepohrdne šálkem dobrého čaje, kaligrafickým brkem a foukací harmonice.
Aktivity