Práce se seznamy v jazyce F#

26. 9. 2023
Doba čtení: 30 minut

Sdílet

Autor: Depositphotos
Budeme se zabývat zdánlivě triviálním tématem: datovým typem seznam (list). Ve skutečnosti se však jedná o velmi flexibilní datový typ, pro jehož zpracování (včetně pattern matchingu) navíc existují speciální syntaktické prvky.

Obsah

1. Práce se seznamy v jazyce F#

2. Konstruktor seznamů

3. Prázdný seznam

4. Využití operátoru range při konstrukci seznamu

5. Rekurzivní definice seznamu a operátor ::

6. Spojení seznamů operátorem @

7. Původní základní funkce pro práci se seznamy

8. Nová alternativa k původním funkcím: vlastnosti (properties) seznamů

9. Seznamy a pattern matching

10. Idiomatický způsob zápisu rekurzivního výpočtu délky seznamu

11. Záleží na pořadí větví v bloku match?

12. Rekurzivní zápis funkce append pro spojení dvou seznamů

13. Implementace funkce append založená na pattern matchingu

14. Součet hodnot všech prvků uložených v seznamu

15. Využití tail rekurze při součtu všech prvků v seznamu

16. Test, zda jsou všechny prvky seznamu kladnými čísly

17. Obsah navazujícího článku

18. Repositář s demonstračními příklady

19. Literatura

20. Odkazy na Internetu

1. Práce se seznamy v jazyce F#

Ve čtvrté části seriálu o programovacím jazyce F# se budeme zabývat zdánlivě triviálním tématem. Popíšeme si totiž způsoby práce s datovým typem seznam (list). Ve skutečnosti se však v programovacích jazycích odvozených od původního jazyka ML jedná o velmi flexibilní datový typ, pro jehož zpracování (a to včetně pattern matchingu) navíc existují speciální syntaktické prvky.

Seznamy (lists) jsou vedle záznamů (record) nejdůležitějším složeným datovým typem programovacího jazyka F#. Jedná se o homogenní datový typ, což znamená, že všechny prvky seznamů musí být stejného typu, což je kontrolováno překladačem (příkladem heterogenních složených typů je právě záznam nebo n-tice).

2. Konstruktor seznamů

Pokud je zřejmé, jaké prvky mají být v seznamu uloženy, lze pro konstrukci seznamů použít následující zápis, v němž jsou prvky umístěny do hranatých závorek a pro jejich vzájemné oddělení se používá středník (nikoli čárka!). Zápis tříprvkového seznamu s prvky typu celé číslo tedy může vypadat následovně:

let x = [1; 2; 3]
 
printf "%A" x

Seznam, který tímto zápisem vznikne, má typ int list:

val x : int list = [1; 2; 3]

Pochopitelně můžeme vytvořit i seznam s prvky jiného typu:

let x = ["foo"; "bar"; "baz"]
 
printf "%A" x

Výsledek:

val x : string list = ["foo"; "bar"; "baz"]

Prvky seznamů mohou být i záznamy, n-tice či další seznamy. Podívejme se na příklad s n-ticemi:

let x = [(1, 2); (2, 3); (3, 4)]
 
printf "%A" x

Překladač v tomto případě opět kontroluje typ, a to rekurzivně (tedy všechny n-tice musí mít pouze dva prvky typu celé číslo):

val x : (int * int) list = [(1, 2); (2, 3); (3, 4)]

Pokus o vytvoření heterogenního seznamu skončí s chybou detekovanou již překladačem:

let x = [1; "foo"; 3]
 
printf "%A" x

Chybová zpráva:

All elements of a list must be of the same type as the first element, which
here is 'int'. This element has type 'string'.

přičemž druhý prvek tohoto seznamu je podtržen, takže je zřejmé, na kterém místě chyba vznikla.

3. Prázdný seznam

Víme již, že speciálním případem n-tice je n-tice bez prvků (unit), která se zapisuje takto:

()

I u seznamů se jedná o speciální případ, o čemž se můžeme velmi snadno přesvědčit po konstrukci prázdného seznamu (tedy uvnitř složených závorek nejsou zapsány žádné prvky):

let x = []
Poznámka: v OCamlu se prázdný seznam nazývá „nil“.

Povšimněte si, jakého typu je tento seznam:

val x : 'a list = []
Poznámka: o speciální případ se zde jedná z toho důvodu, že programovací jazyk F# nedokáže z prázdného seznamu odvodit typ prvků. V mnoha programových konstrukcích tak musí předpokládat, že se může jednat o libovolný seznam, čehož lze někdy využít. Na druhou stranu ovšem můžeme z „typovaného“ seznamu získat prázdný „typovaný“ seznam – postačuje například získat ocas z jednoprvkového seznamu s prvky typu celé číslo. Výsledkem bude prázdný seznam celých čísel.
Poznámka: prázdný seznam se v mnoha ohledech liší od typu unit!

4. Využití operátoru range při konstrukci seznamu

Pro konstrukci seznamů lze využít i operátor range zapisovaný pomocí dvou teček. Seznam s deseti (ne devíti!) prvky 1 až 10 vytvoříme takto:

let x = [1..10]
 
printf "%A" x

Výsledek:

[1; 2; 3; 4; 5; 6; 7; 8; 9; 10]

Určit lze i krok, který se zapisuje na druhou pozici (což může být matoucí; v jiných jazycích se krok a mez přehazují):

let y = [1..2..10]
 
printf "%A" y

Výsledkem budou v tomto případě pouze liché prvky mezi 1 a 10 (včetně):

[1; 3; 5; 7; 9]

Krok může být i záporný. Opět si to otestujme:

let x = [10..-1..0]
 
printf "%A" x

Výsledkem nyní bude jedenáct prvků (včetně nuly):

[10; 9; 8; 7; 6; 5; 4; 3; 2; 1; 0]

A konečně kombinace záporného kroku, který se navíc liší od jedničky:

let y = [10..-2..0]
 
printf "%A" y

Výsledek:

[10; 8; 6; 4; 2; 0]

5. Rekurzivní definice seznamu a operátor ::

Sémantika seznamů je do značné míry převzata z LISPu, ovšem syntaxe práce s nimi je do značné míry odlišná. Seznam může být v tomto kontextu definován rekurzivně:

  • buď je seznam prázdný (což se zapisuje, jak již víme, prázdnými hranatými závorkami [])
  • nebo má formu hlava::ocas, kde hlava je prvním prvkem seznamu a ocas tvoří zbytek prvků seznamu (opět jde o seznam). Operátor :: se nazývá cons.

To ovšem například znamená, že seznam [42] je shodný se seznamem 42::[]. To si ostatně můžeme snadno otestovat:

let x = [42]
printf "%A" x
 
let y = 42::[]
printf "%A" y

Výsledky:

[42]
[42]

Pokusme se podobným způsobem realizovat seznam se třemi prvky:

let x = ["foo"; "bar"; "baz"]
printf "%A" x
 
let y = "foo"::"bar"::"baz"::[]
printf "%A" y

Výsledky:

[foo; bar; baz]
[foo; bar; baz]

Z tohoto demonstračního příkladu si můžeme odvodit dvě vlastnosti programovacího jazyka F#:

  1. Operátor :: je vyhodnocován zprava doleva
  2. Zápis seznamu stylem [prvek1;prvek2;prvek3;…] je ve skutečnosti jen syntaktických cukrem k zápisu prvek1::prvek2::prvek3…::[]
Poznámka: prázdný seznam (nebo jakýkoli jiný seznam) je na konci výrazu s operátorem :: nutností. Nelze tedy zapsat jen 1::2, to není z pohledu jazyka F# úplný výraz.

6. Spojení seznamů operátorem @

Kromě operátoru :: využijeme při práci se seznamy další speciální operátor zapisovaný znakem @. Tento operátor slouží pro spojení dvou seznamů (stejného typu!). Podívejme se na příklad použití:

let x = [1; 2; 3]
let y = [1..10]
let z = x @ y
 
printf "%A" z

Výsledkem bude tento seznam:

[1; 2; 3; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
Poznámka: operátor lze opět řetězit, což ale není nic překvapivého.

Typ spojovaných seznamů si hlídá překladač:

let x = [1; 2; 3]
let y = ["foo"; "bar"; "baz"]
let z = x @ y
 
printf "%A" z

Zde pochopitelně bude nalezena chyba:

Type mismatch. Expecting a
    'int list'
but given a
    'string list'
The type 'int' does not match the type 'string'

7. Původní základní funkce pro práci se seznamy

V programovacím jazyku ML, z něhož jazyk F# vychází, bylo definováno několik základních funkcí určených pro práci se seznamy. Pro zajímavost si tyto funkce vypišme:

Funkce Stručný popis
null(x) test na prázdný seznam
length(x) délka seznamu
hd(x) první prvek seznamu
tl(x) ocas seznamu (bez prvního prvku)
nth(x) n-tý prvek seznamu

Následuje příklad použití funkce null a tl pro rekurzivní výpočet délky seznamu v jazyce ML (SML):

(* Naivní implementace funkce length *)
 
fun len(x) = if null(x) then 0
             else 1 + len(tl(x));
 
len([1,2,3,4]);

8. Nová alternativa k původním funkcím: vlastnosti (properties) seznamů

V jazyce F# výše uvedené funkce nenalezneme. Namísto toho se totiž používají takzvané vlastnosti (properties), které se zapisují s využitím tečkové notace. Všech pět výše uvedených funkcí má svoji obdobu, i když s poněkud odlišnými jmény (používají se celá slova, mj. i proto, že o jejich doplnění se pokouší integrované vývojové prostředí):

Vlastnost Stručný popis
list.IsEmpty test na prázdný seznam
list.Length délka seznamu
list.Head první prvek seznamu
list.Tail ocas seznamu (bez prvního prvku)
list.Item n n-tý prvek seznamu

Podívejme se nyní na základní způsob použití těchto vlastností – budeme zjišťovat informace o seznamu z:

let x = [1; 2; 3]
let y = [1..10]
let z = x @ y
 
printf "list:   %A" z
printf "empty?: %b" z.IsEmpty
printf "length: %d" z.Length
printf "head:   %A" z.Head
printf "tail:   %A" z.Tail
printf "item 3: %A" (z.Item 3)

Výsledky budou vypadat následovně:

list:   [1; 2; 3; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
empty?: false
length: 13
head:   1
tail:   [2; 3; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
item 3: 1

Reimplementace funkce len z předchozí kapitoly může vypadat následovně:

(* Naivní implementace funkce length *)
 
let rec len (x:'a list) =
    if x.IsEmpty then 0
    else 1 + (len x.Tail)
 
printf "%d" (len [1;2;3;4])
Poznámka: povšimněte si, že se v žádném případě nejedná o příliš elegantní zápis (navíc je vyžadováno explicitní určení typu parametru, na což nejsme v jazyce F# zvyklí). Ovšem dále si uvedeme mnohem idiomatičtější způsob zápisu podobné funkce.

9. Seznamy a pattern matching

Operátor ::, o němž jsme se zmínili v předchozích kapitolách, lze využít i při zápisu vzoru (pattern) v bloku match. To tedy znamená, že můžeme zapsat test, zda seznam obsahuje na začátku nějaký prvek, jakou hodnotu má tento prvek atd. Jedná se o velmi silný koncept, která nám umožňuje elegantní realizaci mnoha funkcí, které musí zpracovat prvky seznamu. Většina těchto funkcí zpracovává seznam sekvenčně, tedy nejdříve zpracuje jeho první prvek (hlavu) a poté rekurzivně zbytek seznamu (ocas). Některé ukázky budou uvedeny v navazujících kapitolách.

10. Idiomatický způsob zápisu rekurzivního výpočtu délky seznamu

V osmé kapitole jsme si ukázali rekurzivní zápis funkce pro výpočet délky seznamu. Tuto funkci můžeme velmi snadno přepsat do podoby, v níž se použije pattern matching. Upravený tvar může vypadat následovně a velmi přesně odpovídá teoretickému zápisu algoritmu:

(* Méně naivní implementace funkce length *)
 
let rec len x =
    match x with
    | [] -> 0
    | head :: tail -> 1 + len tail
 
printf "%d" (len [1;2;3;4])

Povšimněte si, že ve větvi začínající vzorkem head :: tail se ve skutečnosti nikde nepracuje s hodnotou prvního prvku seznamu (head). Proto můžeme tento identifikátor nahradit za podtržítko. Výsledkem bude naprosto stejná realizace algoritmu, ovšem bez přebytečných identifikátorů:

(* Méně naivní implementace funkce length *)
 
let rec len x =
    match x with
    | [] -> 0
    | _ :: tail -> 1 + len tail
 
printf "%d" (len [1;2;3;4])

11. Záleží na pořadí větví v bloku match?

V mnoha programovacích jazycích se používá nějaká obdoba konstrukce switch-case, v níž se nějaká hodnota postupně porovnává se vzorky v jednotlivých větvích (a většinou jsou možnosti zápisu vzorků dosti omezené). Mohlo by se tedy zdát, že i v jazyku F# musíme nejdříve otestovat, zda není zpracovávaný seznam prázdný a teprve poté řešit možnost, že seznam obsahuje hlavu (tedy skutečný prvek) a ocas (ten už může být prázdný). Ovšem ve skutečnosti tomu tak přesně není, o čemž se lze velmi snadno přesvědčit, protože i následující příklad je plně funkční, i když mu předáme (přímo či nepřímo) prázdný seznam. Nedojde tedy k pádu ani k vyhození výjimky:

(* Méně naivní implementace funkce length *)
 
let rec len x =
    match x with
    | head :: tail -> 1 + len tail
    | [] -> 0
 
printf "%d" (len [1;2;3;4])

Naproti tomu na pořadí větví záleží – zkuste si prohodit předposlední a poslední větev a zjistit, jaké řetězce se vypíšou:

let rec foo x =
    match x with
    | [] -> "nil"
    | [x] -> "one item"
    | head :: tail -> "more items"
 
printf "%s" (foo [])
printf "%s" (foo [1])
printf "%s" (foo [1; 2])
Poznámka: navíc dokáže překladač zjistit, zda se v bloku match skutečně testují všechny možnosti, které mohou nastat. Pokud se netestují, překladač vypíše varování.

12. Rekurzivní zápis funkce append pro spojení dvou seznamů

Podobně si můžeme nadefinovat funkci append, která vrací nový seznam vzniklý spojením dvou seznamů x a y. Tedy například:

append([1, 2], [3, 4, 5])
[1, 2, 3, 4, 5]

Na problém implementace této funkce můžeme použít princip postupného zjednodušování problému. Známe totiž dva invarianty:

append([],z) == z
append(a :: y, z) == a :: append(y,z)

Postupně tedy budeme zkracovat první seznam až dojdeme do situace, kdy je tento seznam prázdný. Přímo z těchto podmínek je možné odvodit implementaci funkce append:

(* Naivní implementace funkce append *)
 
let rec append (x: 'a list) y =
    if x.IsEmpty then y
    else x.Head :: (append x.Tail y)
 
 
printf "%A" (append [] [1; 2; 3])
printf "%A" (append [1; 2; 3] [])
printf "%A" (append [1; 2; 3] [4; 5])
printf "%A" (append [] [])
Poznámka: navíc se nám automaticky splnily všechny okrajové podmínky, tedy konkrétně situace, kdy je jeden ze seznamů prázdný.

Při zavolání:

append([1,2], [3,4,5])

dojde k postupnému vykonání fáze navíjení a odvíjení, což si můžeme naznačit graficky:

1 :: append([2], [3,4,5])
1 :: 2 :: append([], [3,4,5])
1 :: 2 :: [3,4,5]
1 :: [2,3,4,5]
[1,2,3,4,5]

Důležitý je i typ nové funkce:

val append = fn: ∀ 'a . 'a list * 'a list → 'a list;

Tento zápis nám říká, že funkce bude akceptovat dva seznamy typu „any“ a výsledkem bude další seznam typu „any“. Typ prvků seznamů sice není explicitně určen, ovšem je zaručeno, že oba dva vstupní seznamy budou mít stejný typ prvků, jako seznam výsledný.

13. Implementace funkce append založená na pattern matchingu

V praxi se vždy při zápisu algoritmů, v nichž se vyskytuje plná podoba rozeskoku if-then-else, vyplatí popřemýšlet, zda nebude výhodnější použít pattern matching. U funkce append tomu tak skutečně je, protože její varianta s pattern matchingem je mnohem čitelnější. Je v ní patrné, jak postupně přesunujeme prvky z prvního seznamu do vznikajícího seznamu výsledného (a nakonec připojíme celý druhý seznam):

(* Implementace funkce append založená na pattern matchingu *)
 
let rec append x y =
    match x with
    | [] -> y
    | head :: tail -> head :: append tail y
 
 
printf "%A" (append [] [1; 2; 3])
printf "%A" (append [1; 2; 3] [])
printf "%A" (append [1; 2; 3] [4; 5])
printf "%A" (append [] [])

14. Součet hodnot všech prvků uložených v seznamu

Mnoho operací nad seznamy je založeno na postupném zpracování prvků seznamu, konkrétně od prvku prvního (hlavy). To většinou vede k velmi podobnému zápisu algoritmů, zejména při použití pattern matchingu. Ostatně si můžeme ukázat realizaci dalšího algoritmu, tentokrát algoritmu pro součet všech prvků v seznamu. Řešení bude opět rekurzivní a vzorky použité v bloku match jsou totožné se vzorky z předchozích demonstračních příkladů, což je ovšem logické, protože opět potřebujeme vyřešit dva případy – prázdný seznam a seznam s minimálně jedním prvkem:

let rec sum x =
    match x with
    | [] -> 0
    | head :: tail -> head + sum tail
 
printf "%d" (sum [])
printf "%d" (sum [1; 2; 3])

15. Využití tail rekurze při součtu všech prvků v seznamu

Přímá rekurze, která není v tail pozici a kterou jsme použili při realizaci algoritmu pro součet prvků v seznamu, není v praxi příliš efektivní. Proto se můžeme pokusit o její nahrazení variantou s tail pozicí, což opět (prakticky nutně) vede k použití akumulátoru a vnitřní pomocné funkce, která je založena na tail rekurzi a kterou voláme s předáním akumulované hodnoty. Povšimněte si, že tato funkce (sumr) má dva parametry – seznam a hodnotu akumulátoru a skutečně volá sebe samu v tail pozici (tedy výsledek volané funkce je současně i výsledkem funkce aktuálně prováděné):

let sum x =
    let rec sumr x a =
        match x with
        | [] -> a
        | head :: tail -> sumr tail (a + head)
    sumr x 0
 
printf "%d" (sum [])
printf "%d" (sum [1; 2; 3])
Poznámka: počáteční hodnota akumulátoru je pochopitelně v tomto konkrétním případě nulová.

16. Test, zda jsou všechny prvky seznamu kladnými čísly

V posledním demonstračním příkladu, který si dnes ukážeme, je implementován algoritmus, který zjistí, jestli seznam obsahuje pouze kladná čísla. Pro prázdný seznam byla zvolena výsledná hodnota false, ale to je diskutabilní – můžete si zde dosadit true podle způsobu použití. Povšimněte si, že zde (nově) řešíme případ seznamu s jediným prvkem. Poslední větev v bloku match je již klasická – pokud je první prvek kladný, zjistíme výsledek pro zbytek seznamu a použijeme logický součin:

let rec all_pos x =
    match x with
    | [] -> false
    | [x] -> x > 0
    | head :: tail -> head > 0 && all_pos tail
 
printf "%b" (all_pos [])
printf "%b" (all_pos [1; 2; 3])
printf "%b" (all_pos [-1; 2; 3])
printf "%b" (all_pos [1; 2; -3])

Alternativně můžeme použít vzorek s podmínkou zapsanou ve when. Zjistíme tak kladnost prvku v jednoprvkovém seznamu. Druhá větev (bez when) se v takovém případě nepoužije – záleží zde na pořadí jednotlivých větví:

let rec all_pos x =
    match x with
    | [] -> false
    | [x] when x > 0 -> true
    | [x] -> false
    | head :: tail -> head > 0 && all_pos tail
 
printf "%b" (all_pos [])
printf "%b" (all_pos [1; 2; 3])
printf "%b" (all_pos [-1; 2; 3])
printf "%b" (all_pos [1; 2; -3])

To, že záleží na pořadí větví, si můžete otestovat na příkladu, v němž se můžete pokusit prohodit druhou a třetí větev:

let rec last_pos x =
    match x with
    | [] -> "nil"
    | [x] -> "x<=0"
    | [x] when x > 0 -> "x>0"
    | head :: tail -> last_pos tail
 
printf "%s" (all_pos [])
printf "%s" (all_pos [1; 2; 3])
printf "%s" (all_pos [-1; 2; 3])
printf "%s" (all_pos [1; 2; -3])

17. Obsah navazujícího článku

V navazující části článku o programovacím jazyku F# si popíšeme způsoby práce s dalšími velmi užitečnými datovými typy. V první řadě se jedná o typ Option a typ Result, což jsou v podstatě monády (nelekněte se) použité resp. přesněji řečeno převzaté do programovacího jazyka Rust. A taktéž si popíšeme způsob práce s poli (Array).

18. Repositář s demonstračními příklady

Všechny výše popsané demonstrační příklady byly uloženy do repositáře dostupného na adrese https://github.com/tisnik/f-sharp-examples/. V tabulce umístěné pod tímto odstavcem jsou uvedeny odkazy na tyto příklady:

# Příklad Popis příkladu Cesta
1 ML/fib_recursive.ml výpočet hodnoty z Fibonacciho posloupnosti rekurzivně https://github.com/tisnik/f-sharp-examples/tree/master/ML/fib_re­cursive.ml
2 ML/fib_pattern_matching.ml výpočet hodnoty z Fibonacciho posloupnosti založený na pattern matchingu https://github.com/tisnik/f-sharp-examples/tree/master/ML/fib_pat­tern_matching.ml
3 ML/len_pattern_matching1.ml výpočet délky seznamu založený na pattern matchingu (první varianta) https://github.com/tisnik/f-sharp-examples/tree/master/ML/len_pat­tern_matching1.ml
4 ML/len_pattern_matching2.ml výpočet délky seznamu založený na pattern matchingu (zkrácená varianta) https://github.com/tisnik/f-sharp-examples/tree/master/ML/len_pat­tern_matching2.ml
       
5 OCaml/fib_recursive.ml výpočet hodnoty z Fibonacciho posloupnosti rekurzivně https://github.com/tisnik/f-sharp-examples/tree/master/OCam­l/fib_recursive.ml
6 OCaml/fib_tail_recursive.ml výpočet hodnoty z Fibonacciho posloupnosti s využitím koncové rekurze https://github.com/tisnik/f-sharp-examples/tree/master/OCam­l/fib_tail_recursive.ml
7 OCaml/fib_pattern_matching.ml výpočet hodnoty z Fibonacciho posloupnosti založený na pattern matchingu https://github.com/tisnik/f-sharp-examples/tree/master/OCam­l/fib_pattern_matching.ml
8 OCaml/local_binding.ml symbol lokální uvnitř funkce https://github.com/tisnik/f-sharp-examples/tree/master/OCam­l/local_binding.ml
       
9 article01/function.fs deklarace pojmenované funkce https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle01/function.fs
10 article01/lambda.fs deklarace anonymní funkce https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle01/lambda.fs
11 article01/local_binding1.fs lokální symboly ve funkci https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle01/local_binding1.fs
12 article01/local_binding2.fs lokální symboly ve funkci https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle01/local_binding2.fs
13 article01/function_type1.fs explicitní definice návratového typu funkce (korektní) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle01/function_type1.fs
14 article01/function_type2.fs explicitní definice návratového typu funkce (nekorektní) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle01/function_type2.fs
       
15 article02/basic_binding.fs navázání hodnoty na symbol (deklarace proměnné) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/basic_binding.fs
16 article02/print_variable.fs tisk hodnoty proměnné https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/print_variable.fs
17 article02/variables_and_functions.fs předání proměnné do funkce https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/variables_and_functi­ons.fs
18 article02/redefine_symbol1.fs pokus o redefinici symbolu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/redefine_symbol1.fs
19 article02/redefine_symbol2.fs pokus o redefinici symbolu (složitější příklad) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/redefine_symbol2.fs
       
20 article02/equal_operator1.fs operátor = https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/equal_operator1.fs
21 article02/equal_operator2.fs operátor = https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/equal_operator2.fs
       
22 article02/immutable_variable.fs „změna“ neměnitelné proměnné https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/immutable_variable.fs
23 article02/mutable_variable.fs změna měnitelné proměnné https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/mutable_variable.fs
24 article02/reference1.fs reference, příklad kompatibilní s OCamlem https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/reference1.fs
25 article02/reference2.fs reference, nová syntaxe pro F# https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/reference2.fs
26 article02/incr1.fs standardní funkce incr https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/incr1.fs
27 article02/incr2.fs zvýšení referencované hodnoty o jedničku https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/incr2.fs
28 article02/shadow.fs shadowing symbolu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/shadow.fs
       
29 article02/tuple.fs datový typ n-tice (tuple) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/tuple.fs
30 article02/record1.fs datový typ záznam (record), deklarace proměnné tohoto typu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/record1.fs
31 article02/record2.fs datový typ záznam (record) a typová inference při deklaraci proměnné https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/record2.fs
       
32 article02/basic_binding.fsx demonstrační příklad basic_binding.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/basic_binding.fsx
33 article02/equal_operator1.fsx demonstrační příklad equal_operator1.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/equal_operator1.fsx
34 article02/equal_operator2.fsx demonstrační příklad equal_operator2.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/equal_operator2.fsx
35 article02/immutable_variable.fsx demonstrační příklad immutable_variable.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/immutable_variable.fsx
36 article02/mutable_variable.fsx demonstrační příklad mutable_variable.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/mutable_variable.fsx
37 article02/print_variable.fsx demonstrační příklad print_variable.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/print_variable.fsx
38 article02/redefine_symbol1.fsx demonstrační příklad redefine_symbol1.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/redefine_symbol1.fsx
39 article02/redefine_symbol2.fsx demonstrační příklad redefine_symbol2.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/redefine_symbol2.fsx
40 article02/variables_and_functions.fsx demonstrační příklad variables_and_functions.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/variables_and_functi­ons.fsx
41 article02/incr1.fsx demonstrační příklad incr1.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/incr1.fsx
42 article02/incr2.fsx demonstrační příklad incr2.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/incr2.fsx
43 article02/reference1.fsx demonstrační příklad reference1.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/reference1.fsx
44 article02/reference2.fsx demonstrační příklad reference2.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/reference2.fsx
45 article02/ident.fsx demonstrační příklad ident.fs přepsaný do podoby skriptu pro dotnet fsi https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle02/ident.fsx
       
46 article03/recursion1.fs pokus o deklaraci funkce s přímou rekurzí založený na let https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/recursion1.fs
47 article03/recursion2.fs deklarace funkce s přímou rekurzí založená na let rec https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/recursion2.fs
48 article03/recursion3.fs využití tail rekurze pro výpočet členu Fibonacciho posloupnosti https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/recursion3.fs
49 article03/recursion4.fs obyčejná nerekurzivní funkce definovaná přes let rec https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/recursion4.fs
       
50 article03/odd_even1.fs nepřímá rekurze (nekorektní varianta) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/odd_even1.fs
51 article03/odd_even2.fs nepřímá rekurze (taktéž nekorektní varianta) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/odd_even2.fs
52 article03/odd_even3.fs jediný korektní zápis nepřímé rekurze https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/odd_even3.fs
53 article03/odd_even4.fs nepřímá rekurze bez použití klíčového slova rec https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/odd_even4.fs
       
54 article03/pattern1.fs výpočet Faktoriálu založený na pattern matchingu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/pattern1.fs
55 article03/pattern2.fs výpočet Faktoriálu založený na pattern matchingu, sloučení vstupů se stejným výstupem https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/pattern2.fs
56 article03/pattern3.fs kontrola neplatného vstupu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/pattern3.fs
57 article03/pattern4.fs pattern matching pro větší množství hodnot https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/pattern4.fs
58 article03/pattern5.fs rekurzivní implementace Ackermannovy funkce https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/pattern5.fs
59 article03/pattern6.fs kontrola neplatných vstupních hodnot pro Ackermannovu funkci https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/pattern6.fs
       
60 article03/fibonacci1.fs výpočet Fibonacciho posloupnosti založený na pattern matchingu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/fibonacci1.fs
61 article03/fibonacci2.fs výpočet Fibonacciho posloupnosti založený na pattern matchingu (více idiomatický zápis) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/fibonacci2.fs
       
62 article03/first.fs funkce vracející první prvek z dvojice založená na pattern matchingu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/first.fs
63 article03/second.fs funkce vracející druhý prvek z dvojice založená na pattern matchingu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/second.fs
64 article03/zero_coordinate.fs test na nulovou souřadnici/souřadnice založený na pattern matchingu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/zero_coordinate.fs
       
65 article03/get_model.fs získání prvku ze záznamu (opět založeno na pattern matchingu) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle03/get_model.fs
       
66 article04/list_literal1.fs seznam se třemi prvky typu celé číslo https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/list_literal1.fs
67 article04/list_literal2.fs seznam se třemi prvky typu řetězec https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/list_literal2.fs
68 article04/list_literal3.fs seznam se třemi prvky typu n-tice https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/list_literal3.fs
69 article04/list_literal4.fs nekorektní pokus o vytvoření seznamu s prvky různých typů https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/list_literal4.fs
70 article04/empty_list.fs konstrukce prázdného seznamu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/empty_list.fs
       
71 article04/head_tail1.fs složení seznamu se dvěma prvky s využitím operátoru :: https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/head_tail1.fs
72 article04/head_tail2.fs složení seznamu se třemi prvky s využitím operátoru :: https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/head_tail2.fs
       
73 article04/list_properties.fs vlastnosti (properties) seznamů https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/list_properties.fs
74 article04/len1.fs naivní rekurzivní výpočet délky seznamu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/len1.fs
75 article04/len2.fs vylepšený rekurzivní výpočet délky seznamu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/len2.fs
76 article04/len3.fs vylepšený rekurzivní výpočet délky seznamu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/len3.fs
       
77 article04/range1.fs vytvoření sekvence numerických hodnot s využitím operátoru range https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/range1.fs
78 article04/range2.fs vytvoření sekvence numerických hodnot s využitím operátoru range https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/range2.fs
79 article04/range3.fs vytvoření sekvence numerických hodnot s využitím operátoru range https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/range3.fs
80 article04/range4.fs vytvoření sekvence numerických hodnot s využitím operátoru range https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/range4.fs
       
81 article04/join_lists.fs spojení dvou seznamů operátorem :: https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/join_lists.fs
82 article04/append1.fs implementace spojení dvou seznamů rekurzivním výpočtem https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/append1.fs
83 article04/append2.fs implementace spojení dvou seznamů rekurzivním výpočtem, použití pattern matchingu https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/append2.fs
       
84 article04/sum1.fs součet hodnot všech prvků v seznamu (bez tail rekurze) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/sum1.fs
85 article04/sum2.fs součet hodnot všech prvků v seznamu (s využitím tail rekurze) https://github.com/tisnik/f-sharp-examples/tree/master/arti­cle04/sum2.fs

19. Literatura

Poznámka: v této kapitole jsou uvedeny knihy o jazyku ML resp. Standard ML i knihy o programovacím jazyku OCaml, který ze Standard ML ze značné míry vychází. A samozřejmě nezapomeneme ani na knihy o jazyku F#:
  1. Get Programming with F#
    https://www.manning.com/books/get-programming-with-f-sharp
  2. F# for Scientists
    https://www.amazon.com/F-Scientists-Jon-Harrop-ebook/dp/B005PS97RO
  3. Domain Modeling Made Functional
    https://fsharpforfunandpro­fit.com/books/
  4. Functional Programming with F# (na Overleaf, tedy i se zdrojovými kódy)
    https://www.overleaf.com/pro­ject/5bf2cb3cd9568d5a75bfcb­a9
  5. Book of F#
    https://nostarch.com/fsharp
  6. F# Programming (Wikibook)
    https://en.wikibooks.org/wi­ki/F_Sharp_Programming
  7. Stylish F#: Crafting Elegant Functional Code for .NET and .NET Core
    https://www.amazon.com/dp/1484239997/
  8. ML for the Working Programmer
    https://www.cl.cam.ac.uk/~lp15/MLbo­ok/pub-details.html
  9. Elements of ML Programming, 2nd Edition (ML97)
    http://infolab.stanford.e­du/~ullman/emlp.html
  10. A tour of Standard ML
    https://saityi.github.io/sml-tour/tour/welcome
  11. The History of Standard ML
    https://smlfamily.github.i­o/history/SML-history.pdf
  12. The Standard ML Basis Library
    https://smlfamily.github.io/Basis/
  13. Programming in Standard ML
    http://www.cs.cmu.edu/~rwh/is­ml/book.pdf
  14. Programming in Standard ML '97: A Tutorial Introduction
    http://www.lfcs.inf.ed.ac­.uk/reports/97/ECS-LFCS-97–364/
  15. Programming in Standard ML '97: An On-line Tutorial
    https://homepages.inf.ed.ac­.uk/stg/NOTES/
  16. The OCaml system release 4.13
    https://ocaml.org/releases/4­.13/htmlman/index.html
  17. Real World OCaml: Functional programming for the masses
    https://dev.realworldocaml.org/
  18. OCaml from the Very Beginning
    http://ocaml-book.com/
  19. OCaml from the Very Beginning: More OCaml : Algorithms, Methods & Diversions
    http://ocaml-book.com/more-ocaml-algorithms-methods-diversions/
  20. Unix system programming in OCaml
    http://ocaml.github.io/ocamlunix/
  21. OCaml for Scientists
    https://www.ffconsultancy­.com/products/ocaml_for_sci­entists/index.html
  22. Using, Understanding, and Unraveling The OCaml Language
    https://caml.inria.fr/pub/docs/u3-ocaml/
  23. Developing Applications With objective Caml
    https://caml.inria.fr/pub/docs/oreilly-book/index.html
  24. Introduction to Objective Caml
    http://courses.cms.caltech­.edu/cs134/cs134b/book.pdf
  25. How to Think Like a (Functional) Programmer
    https://greenteapress.com/thin­kocaml/index.html

20. Odkazy na Internetu

  1. General-Purpose, Industrial-Strength, Expressive, and Safe
    https://ocaml.org/
  2. OCaml playground
    https://ocaml.org/play
  3. Online Ocaml Compiler IDE
    https://www.jdoodle.com/compile-ocaml-online/
  4. Get Started – OCaml
    https://www.ocaml.org/docs
  5. Get Up and Running With OCaml
    https://www.ocaml.org/docs/up-and-running
  6. Better OCaml (Online prostředí)
    https://betterocaml.ml/?ver­sion=4.14.0
  7. OCaml file extensions
    https://blog.waleedkhan.name/ocaml-file-extensions/
  8. First thoughts on Rust vs OCaml
    https://blog.darklang.com/first-thoughts-on-rust-vs-ocaml/
  9. Standard ML of New Jersey
    https://www.smlnj.org/
  10. Programming Languages: Standard ML – 1 (a navazující videa)
    https://www.youtube.com/wat­ch?v=2sqjUWGGzTo
  11. 6 Excellent Free Books to Learn Standard ML
    https://www.linuxlinks.com/excellent-free-books-learn-standard-ml/
  12. SOSML: The Online Interpreter for Standard ML
    https://sosml.org/
  13. ML (Computer program language)
    https://www.barnesandnoble­.com/b/books/other-programming-languages/ml-computer-program-language/_/N-29Z8q8Zvy7
  14. Strong Typing
    https://perl.plover.com/y­ak/typing/notes.html
  15. What to know before debating type systems
    http://blogs.perl.org/user­s/ovid/2010/08/what-to-know-before-debating-type-systems.html
  16. Types, and Why You Should Care (Youtube)
    https://www.youtube.com/wat­ch?v=0arFPIQatCU
  17. DynamicTyping (Martin Fowler)
    https://www.martinfowler.com/bli­ki/DynamicTyping.html
  18. DomainSpecificLanguage (Martin Fowler)
    https://www.martinfowler.com/bli­ki/DomainSpecificLanguage­.html
  19. Language Workbenches: The Killer-App for Domain Specific Languages?
    https://www.martinfowler.com/ar­ticles/languageWorkbench.html
  20. Effective ML (Youtube)
    https://www.youtube.com/watch?v=-J8YyfrSwTk
  21. Why OCaml (Youtube)
    https://www.youtube.com/wat­ch?v=v1CmGbOGb2I
  22. CSE 341: Functions and patterns
    https://courses.cs.washin­gton.edu/courses/cse341/04wi/lec­tures/03-ml-functions.html
  23. Comparing Objective Caml and Standard ML
    http://adam.chlipala.net/mlcomp/
  24. What are the key differences between Standard ML and OCaml?
    https://www.quora.com/What-are-the-key-differences-between-Standard-ML-and-OCaml?share=1
  25. Cheat Sheets (pro OCaml)
    https://www.ocaml.org/doc­s/cheat_sheets.html
  26. Syllabus (FAS CS51)
    https://cs51.io/college/syllabus/
  27. Abstraction and Design In Computation
    http://book.cs51.io/
  28. Learn X in Y minutes Where X=Standard ML
    https://learnxinyminutes.com/doc­s/standard-ml/
  29. CSE307 Online – Summer 2018: Principles of Programing Languages course
    https://www3.cs.stonybrook­.edu/~pfodor/courses/summer/cse307­.html
  30. CSE307 Principles of Programming Languages course: SML part 1
    https://www.youtube.com/wat­ch?v=p1n0_PsM6hw
  31. CSE 307 – Principles of Programming Languages – SML
    https://www3.cs.stonybrook­.edu/~pfodor/courses/summer/CSE307/L01_SML­.pdf
  32. SML, Some Basic Examples
    https://cs.fit.edu/~ryan/sml/in­tro.html
  33. History of programming languages
    https://devskiller.com/history-of-programming-languages/
  34. History of programming languages (Wikipedia)
    https://en.wikipedia.org/wi­ki/History_of_programming_lan­guages
  35. Jemný úvod do rozsáhlého světa jazyků LISP a Scheme
    https://www.root.cz/clanky/jemny-uvod-do-rozsahleho-sveta-jazyku-lisp-a-scheme/
  36. The Evolution Of Programming Languages
    https://www.i-programmer.info/news/98-languages/8809-the-evolution-of-programming-languages.html
  37. Evoluce programovacích jazyků
    https://ccrma.stanford.edu/cou­rses/250a-fall-2005/docs/ComputerLanguagesChart.png
  38. Poly/ML Homepage
    https://polyml.org/
  39. PolyConf 16: A brief history of F# / Rachel Reese
    https://www.youtube.com/wat­ch?v=cbDjpi727aY
  40. Programovací jazyk Clojure 18: základní techniky optimalizace aplikací
    https://www.root.cz/clanky/pro­gramovaci-jazyk-clojure-18-zakladni-techniky-optimalizace-aplikaci/
  41. Moscow ML Language Overview
    https://itu.dk/people/ses­toft/mosml/mosmlref.pdf
  42. ForLoops
    http://mlton.org/ForLoops
  43. Funkcionální dobrodružství v JavaScriptu
    https://blog.kolman.cz/2015/12/fun­kcionalni-dobrodruzstvi-v-javascriptu.html
  44. Recenze knihy Functional Thinking (Paradigm over syntax)
    https://www.root.cz/clanky/recenze-knihy-functional-thinking-paradigm-over-syntax/
  45. Currying
    https://sw-samuraj.cz/2011/02/currying/
  46. Používání funkcí v F#
    https://docs.microsoft.com/cs-cz/dotnet/fsharp/tutorials/using-functions
  47. Funkce vyššího řádu
    http://naucte-se.haskell.cz/funkce-vyssiho-radu
  48. Currying (Wikipedia)
    https://en.wikipedia.org/wi­ki/Currying
  49. Currying (Haskell wiki)
    https://wiki.haskell.org/Currying
  50. Haskell Curry
    https://en.wikipedia.org/wi­ki/Haskell_Curry
  51. Moses Schönfinkel
    https://en.wikipedia.org/wi­ki/Moses_Sch%C3%B6nfinkel
  52. .NET framework
    https://dotnet.microsoft.com/en-us/
  53. F# – .NET Blog
    https://devblogs.microsof­t.com/dotnet/category/fshar­p/
  54. Playground: OCaml
    https://ocaml.org/play
  55. The F# Survival Guide
    https://web.archive.org/web/20110715231625/htt­p://www.ctocorner.com/fshar­p/book/default.aspx
  56. Object-Oriented Programming — The Trillion Dollar Disaster
    https://betterprogramming.pub/object-oriented-programming-the-trillion-dollar-disaster-92a4b666c7c7
  57. Goodbye, Object Oriented Programming
    https://cscalfani.medium.com/goodbye-object-oriented-programming-a59cda4c0e53
  58. So You Want to be a Functional Programmer (Part 1)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-1–1f15e387e536
  59. So You Want to be a Functional Programmer (Part 2)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-2–7005682cec4a
  60. So You Want to be a Functional Programmer (Part 3)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-3–1b0fd14eb1a7
  61. So You Want to be a Functional Programmer (Part 4)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-4–18fbe3ea9e49
  62. So You Want to be a Functional Programmer (Part 5)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-5-c70adc9cf56a
  63. So You Want to be a Functional Programmer (Part 6)
    https://cscalfani.medium.com/so-you-want-to-be-a-functional-programmer-part-6-db502830403
  64. Why Programmers Need Limits
    https://cscalfani.medium.com/why-programmers-need-limits-3d96e1a0a6db
  65. Signatures
    https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/signature-files
  66. F# for Linux People
    https://carpenoctem.dev/blog/fsharp-for-linux-people/
  67. Ionide project
    https://ionide.io/
  68. FsAutoComplete
    https://ionide.io/Tools/fsac.html
  69. Interactive (.NET for Jupyter Notebook)
    https://github.com/dotnet/in­teractive/#jupyter-and-nteract
  70. let Bindings
    https://github.com/dotnet/doc­s/blob/main/docs/fsharp/lan­guage-reference/functions/let-bindings.md
  71. Lambda Expressions: The fun Keyword (F#)
    https://github.com/dotnet/doc­s/blob/main/docs/fsharp/lan­guage-reference/functions/lambda-expressions-the-fun-keyword.md
  72. Infographic showing code complexity vs developer experience
    https://twitter.com/rossi­pedia/status/1580639227313676288
  73. OCaml for the Masses: Why the next language you learn should be functional
    https://queue.acm.org/deta­il.cfm?id=2038036
  74. Try EIO
    https://patricoferris.github.io/try-eio/
  75. Try OCaml
    https://try.ocaml.pro/
  76. ML – funkcionální jazyk s revolučním typovým systémem
    https://www.root.cz/clanky/ml-funkcionalni-jazyk-s-revolucnim-typovym-systemem/
  77. Funkce a typový systém programovacího jazyka ML
    https://www.root.cz/clanky/funkce-a-typovy-system-programovaciho-jazyka-ml/
  78. Curryfikace (currying), výjimky a vlastní operátory v jazyku ML
    https://www.root.cz/clanky/curryfikace-currying-vyjimky-a-vlastni-operatory-v-jazyku-ml/
  79. Operátor J (Wikipedia)
    https://en.wikipedia.org/wi­ki/J_operator
  80. Standard ML (Wikipedia)
    https://en.wikipedia.org/wi­ki/Standard_ML
  81. Don Syme
    https://en.wikipedia.org/wi­ki/Don_Syme
  82. Python to OCaml: Retrospective
    http://roscidus.com/blog/blog/2014/06/0­6/python-to-ocaml-retrospective/
  83. Xavier Leroy
    https://en.wikipedia.org/wi­ki/Xavier_Leroy
  84. Unit type
    https://en.wikipedia.org/wi­ki/Unit_type

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.