Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
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í.

Lekce 2 - První funkce v Haskell

V minulé lekci, Úvod do funkcionálního programování, jsme si ukázali, v čem by mohlo být neprocedurální, zvláště pak logické programování užitečné. V dnešní lekci si již zkusíme něco napsat. Pokud nemáte zatím zkušenosti s žádným programovacím jazykem (funkce, cykly, proměnné, řetězce), pak bych doporučoval se nejdříve seznámit s běžným procedurálním programováním, abyste mohli patřičně ocenit programování funkcionální. Jste-li ale odvážlivci, i tak směle pokračujte ve čtení :)

Instalace

Prvně je třeba si stáhnout compiler pro jazyk Haskell. Doporučoval bych GHC (Glasgow Haskell Compiler). Můžete si ho stáhnout pro Windows, Linux i MacOS na URL adrese https://www.haskell.org/platform/. Po instalaci si vytvořte kdekoliv složku Haskell/. Pokud jste nikdy předtím neviděli konzoli, může to pro vás být trochu šok, ale otevřeme si konzoli. Na Linuxu máme přímo Terminal, ve kterém se pomocí příkazu cd dostaneme do naší složky. Pokud nevíte, jak s Linuxem pracovat, doporučuji náš kurz Základy Linuxu. Ve Windows si otevřeme Start, napíšeme cmd a spustíme příkazovou řádku. Napíšeme cd, mezeru a pak přetáhneme složku Haskell do příkazového řádku, jako bychom kopírovali soubor:

Přetažení složky Haskell do okna terminálu - Haskell

Ve skutečnosti kopírujeme jen cestu k souboru a tajemný příkaz cd znamená prostě Change Directory = změň adresář.

Nyní si spustíme GHC pomocí příkazu ghci (GHC interactive). Otevře se nám tzv. prompt. Prelude> vám jen pomáhá odsadit od začátku stránky, nemá žádný sémantický význam.

Spuštění Haskell překladače v příkazové řádce - Haskell

První údery do klávesnice

Zkusíme si konzoli osahat jako by to udělalo malé dítě - jednoduše tam něco namačkáme a podíváme se, co se stane. Po vložení čísla se objeví číslo. Po vložení písmen se objeví "not in scope", což ve volném překladu znamená – neznám. Pokud to samé však dáme text do uvozovek, objeví se nám opět ten samý text. Pokud vložíme -- a za to nějaký text, nestane se nic. A po vložení (+) na nás konzole zakřičí nějakou ošklivou errorovou hlášku. Objevili jsme první pravidla pro psaní v Haskell.

Funkce, proměnné, konstanty a komentáře

Prozatím si vystačíme s tím, že v Haskell máme tři typy "věcí".

Konstanty

Konstanta může být typu Int, Float, Char, String, Boolean atd. Jak jsme zvyklí z jiných jazyků. Proto překladač po vložení 0, "0", '0' a False nebude nic namítat.

Funkce

Když vložíme 5 + 3, vyjede nám 8. Aneb (+) je funkce, která bere 2 argumenty a vrací jeden.

Proměnné

Třetím typem konstrukcí jazyka Haskell jsou proměnné, které začínají malým písmenem, nebo podtržítkem. Napišme si let dva = 2. Potom kdykoliv napíšeme dva, zobrazí se 2. Slůvko let je něco jako interaktivní přiřazení do proměnné či do funkce.

Kalkulačka

Co se týká kalkulací, Haskell umí precizně pracovat s velkými čísly. Zkusme si třeba napsat 123456789^12345. To žádná kalkulačka bez protestů nevezme.

"Kalkulačka" v konzoli umí tyto operace:

((2+5 - 49*100 )/ 3^2 ) * (-5)      -- záporná čísla musí být v závorkách
"ahooj" ++ " svete!"            -- spojování stringů
True && True                    -- logické and
True || False               -- logické or
not True                -- negace
1==0                    -- rovnost
1/=0                    -- nerovnost

Komentáře

Sekvence -- v textu výše jsou samozřejmě komentáře, poznámky pro programátora, kterých si Haskell nevšímá.

Funkce

Kalkulačka nás na 15 sekund zabaví, ale brzy to začne být nuda. Tak se proto podívejme na něco lepšího. Funkce je v Haskell stavební kámen všeho. I vložení 5 je vlastně funkce identita na 5. Zkusme si to. Napišme 5 a pak zkusme napsat id 5. Výsledek je ten samý. Téma funkcí je natolik důležité, že mu budeme věnovat zbytek dnešní lekce.

Funkce je něco jako tajemná krabička s jednou nebo více vstupními proměnnými a jedním výstupem. Funkce musí mít výstup a to právě jeden. Poznali jsme už funkci identity, což je v podstatě taková roura. Co vložíte, to i vypadne ven. Zkusme si napsat sami složitější funkci inc, která vezme číslo a zvýší ho o jedna.

let inc x = x + 1. Slůvko let již známe, je to interaktivní příkaz přiřazení. inc je název funkce, x je její parametr. Tato funkce dělá přesně to, co jí napíšeme. Jakmile dostane x, vrátí x + 1. Zkuste si nyní sami napsat funkci vynasob2 a vrat0. První vynásobí číslo 2, druhá funkce vrátí 0 na cokoliv, co jí pošlete. Když již máme funkci zadefinovanou, volání je snadné: inc 4 a kompiler odpoví 5.

Skládání funkcí

Co by to bylo ale za svět, kdybychom nemohli použít stavebnici z malých funkcí, které jsme si již napsali. Zkusme si nyní napsat funkci, která zvýší proměnnou o 2, neboli inc2:

let inc2 x = inc ( inc x)
let inc2 x = inc $ inc x

Oba zápisy jsou ekvivalentní, znak $ supluje závorky až do konce řádku. Časem uvidíme, že používání dolaru je velmi praktické, ale závorky rozhodně nikomu vadit nebudou. Co se vlastně při spojování funkcí děje? Nejlépe si to představíme jako vlak. Něco vložíme do jednoho vagónu, on s tím něco udělá, pošle to dále atd... Uvědomme si, že nemá smysl mluvit o funkcích se stejným slovníkem jako např. v Javě či v C++. Nějaké předávání hodnotou? Odkazem? private, public, static... Funkce v Haskellu fungují úplně jinak.

Funkce zde nemají žádné vedlejší efekty. Tzn. něco do nich pošleme, něco z nich vyjde. Pošleme do nich to samé a vyjde z nich to samé. Odpadají starosti s tím, že čteme z nějaké proměnné, ale jiné vlákno do ní před chvílí zapsalo, ale my jsme si to neošetřili a ono... Ne, nic takového v Haskellu není. Haskell se proto velmi hodí na paralelní zpracování, protože prostě nemá žádné vedlejší efekty. Přesto jsou někde potřeba a časem se naučíme jak něco jako vedlejší efekt do Haskellu propašovat, ale to nám bude ještě chvíli trvat. Pro procvičení si můžete zkusit napsat pár funkcí do příště:

vynasob3 x y z  -- funkce vynásobí 3 čísla
zalziMi x   -- funkce dostane boolean, třeba zalziMi (3 == 5) a řekne pravý opak. (z True na False a obráceně), parametr musíte zadat v závorkách a i když i v Haskellu jde napsat if, vystačíte si nádherně bez něj.
dec x       -- sníží x o jedna

Uložení do souboru

Když již máme hodně funkcí, je trochu obtížné si je všechny pamatovat a bylo by dobré si je někam uložit, třeba do souboru prvni.hs. Je důležité přiřadit souboru příponu .hs, neboť tak kompilátor pozná, že jde o Haskell source. Buď můžete přímo v konzoli napsat :e muj.hs a objeví se vám ve Windows poznámkový blok, v Linuxu nejspíše nano, nebo můžete rovnou otevřít editor a uložit soubor pod jménem prvni.hs. Pro Windows je poznámkový blok ideální, pro Linux si můžete nastavit třeba vim pomocí :set editor vim. Do souboru prvni.hs si uložte všechny funkce, které jsme si dnes definovali a potom se vraťte do ghci. V něm zadejte :l prvni.hs nebo :load prvni.hs a měla by se vám objevit hláška "OK, modules load". Nyní, pokud změníte něco ve svém zdrojovém souboru, stačí do ghci napsat jen :r jako reload a máte opět načteno. Ve výsledku je tedy velmi pohodlné programovat třeba takto:

Navod - Haskell

Příště, v lekci Haskell - Tebe bych typoval na funkci..., se pustíme již do zajímavějších funkcí a datových struktur. Tak se těšte. Řešení k příkladům přikládám v haskellovském zdrojáku.


 

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 320x (111 B)

 

Předchozí článek
Úvod do funkcionálního programování
Všechny články v sekci
Haskell
Přeskočit článek
(nedoporučujeme)
Haskell - Tebe bych typoval na funkci...
Článek pro vás napsal Ondřej Michálek
Avatar
Uživatelské hodnocení:
9 hlasů
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