Elm: kombinace možností ML jazyka s prostředím JavaScriptu

Dnes
Doba čtení: 36 minut

Sdílet

Autor: Depositphotos
V roce 2021 představil Evan Czaplicki jazyk Elm, který poměrně unikátním způsobem kombinuje možnosti jazyka z rodiny ML (SML, OCaml, F#) s prostředím JavaScriptu, především pak s frameworky pro uživatelské rozhraní.

Na trojici článků o transpřekladači jazyka Standard ML nazvaném LunarML [1] [2] [3] dnes navážeme, protože se budeme zabývat dalším programovacím jazykem z rodiny ML, do které spadá jak původní ML (Meta Language), tak i Standard ML, CAML (Categorical Abstract Machine Language), OCaml (Objective Caml), jazyk F# a do značné míry taktéž Haskell. Všechny tyto jazyky mají společné rysy: jsou funkcionální, mají podobný typový systém, využívají typovou inferenci, mají zabudovanou podporu pro pattern matching atd. Připomeňme si, že LunarML dokáže překládat, resp. přesněji řečeno transpřekládat zdrojové kódy napsané ve Standard ML do jazyka Lua a taktéž do JavaScriptu.

Co se dozvíte v článku
  1. Jazyk Elm – kombinace možností ML jazyka s prostředím JavaScriptu
  2. Nejdůležitější vlastnosti Elmu
  3. Jazyk Elm vs primární funkce JavaScriptových frameworků pro front end
  4. Je Elm mrtvým jazykem, který se dále nevyvíjí?
  5. Nechtěný důsledek: přesnější odpovědi získávané z velkých jazykových modelů
  6. Instalace interpretru a překladače jazyka Elm
  7. Použití interaktivní smyčky REPL
  8. Klávesové zkratky použitelné v REPLu
  9. Uživatelsky příjemná chybová hlášení překladače a interpretru
  10. Typový systém programovacího jazyka Elm
  11. Složené datové typy
  12. Standardní operátory, priorita a asociativita operátorů
  13. Definice funkcí a typová inference
  14. Funkce s větším počtem parametrů
  15. Příklady typových definic standardních funkcí
  16. Obsah navazujícího článku
  17. Literatura
  18. Předchozí články o jazyku ML/SML i o jazycích OCaml a F#
  19. Odkazy na Internetu

V dnešním článku se zaměříme právě na problematiku transpřekladu do JavaScriptu, protože mnoho v současnosti provozovaných či vyvíjených aplikací má svůj front end realizován ve webovém prohlížeči vybaveném právě interpretrem JavaScriptu (a navíc i virtuálním strojem pro WASM). Z tohoto důvodu je dobré mít k dispozici vhodné technologie, typicky transpřekladače, které umožní generovat zdrojový kód v JavaScriptu, jenž bude přímo spustitelný ve webovém prohlížeči. Takových transpřekladačů vzniklo minimálně několik desítek, možná i stovek.

Pravděpodobně nejznámější je transpiler jazyka TypeScript, který se snaží o řešení některých problémů typového systému JavaScriptu (a při té příležitosti jazyk dále vylepšuje, má mnohem lepší chybová hlášení apod.). I pro rodinu jazyků ML máme k dispozici podobné nástroje. O LunarML jsme se zmínili. Dále pro Standard ML existuje projekt SOSML (https://sosml.org/), což je interaktivní webové prostředí. Pro jazyk OCaml existuje projekt nazvaný js_of_ocaml neboli zkráceně jsoo. Nejedná se o samostatný transpřekladač, protože je nutné mít nainstalován prakticky celý ekosystém OCamlu (opam apod). A pro jazyk F# existuje (trans)překladač nazvaný Fable.

Poznámka: technologiím, které dokážou zpřístupnit prostředí JavaScriptu (tedy i možnost běhu ve webových prohlížečích) těm vývojářům, kteří používají programovací jazyky OCaml a F# se budeme podrobněji věnovat v navazujících článcích.

Jazyk Elm – kombinace možností ML jazyka s prostředím JavaScriptu

Všechny původní programovací jazyky z rodiny ML (tedy ML, Standard ML, CAML, OCaml, F#) byly navrženy takovým způsobem, že se jedná o překladače do nativního kódu popř. v případě jazyka F# do bajtkódu CLR (Common Language Runtime). Podpora pro prostředí JavaScriptu byla přidána až později a stále se jedná pouze o transpřekladač a nikoli o plnohodnotnou integraci vyžadovanou moderními webovými aplikacemi. V této situaci vznikl zcela nový programovací jazyk nazvaný Elm, který je přímo určen pro tvorbu webových aplikací (a tím pádem i pro kooperaci s prostředím JavaScriptu). Tento jazyk patří do rodiny ML, takže v něm nalezneme podobný typový systém i podobnou práci s chybějícími hodnotami a výjimkami.

Ovšem to není vše, protože Elm přímo podporuje manipulaci s DOMem webových stránek (DOM je představován základními datovými strukturami Elmu), je podporován návrhový vzor Model-View-Update atd. (ten je vlastně součástí samotného jazyka, nikoli frameworku). V tomto ohledu vznikla možná poněkud paradoxní situace – Elm je totiž lépe uzpůsoben tvorbě webových aplikací, než samotný JavaScript (který ke své roli přišel jako příslovečný slepý k houslím).

Ale to zdaleka není vše – samotný způsob použití Elmu je z pohledu uživatele-programátora velmi snadný a nevyžaduje další znalosti ekosystému JavaScriptu (balíčkovací nástroje, lokální interpretry atd.). Z tohoto pohledu je Elm velmi přívětivý. A nesmíme zapomenout ani na srozumitelná chybová hlášení, která kromě informace o chybě ukazují i na (předpokládaná) správná řešení. V tomto ohledu se Elm podobá Rustu; ve skutečnosti se Rust v této oblasti inspiroval právě Elmem.

Nejdůležitější vlastnosti Elmu

Poměrně mnoho vlastností programovacího jazyka Elm je odvozeno od klasických ML jazyků (vidět je například vliv OCamlu, ostatně i autor Elmu se zmiňuje o tom, že OCaml používal na universitě) a taktéž od Haskellu. Elm je funkcionální programovací jazyk, který nabízí silný typový systém doplněný o mechanismus typové inference. Kontroly prováděné překladačem mají za cíl zajistit stav, ve kterém nebude docházet k běhovým výjimkám způsobených například hodnotami nekorektních typů, neúplným pokrytím všech možných podmínek, které mohou nastat atd. Jedná se tedy o cíl, který má i programovací jazyk Rust. K dispozici jsou všechny potřebné datové typy, včetně Result, záznamů, seznamů, n-tic atd.

Elm navíc nabízí přímou manipulaci s objekty tvořícími HTML stránky, k čemuž používá mechanismus Model, View, Update určující a vlastně i řídicí, jakým způsobem bude HTML stránka „zaintegrována“ s vlastním programem (více si řekneme v samostatném článku). Díky tomu se Elm jakožto jazyk primárně určený pro tvorbu front endu (SPA) obejde bez nutnosti používání front end frameworku.

Samotná sada nástrojů jazyka Elm je vlastně minimalistická a nevyžaduje žádné další utility typu npm atd. Postačuje pouze stáhnout jediný binární soubor obsahující jak překladač, tak i interaktivní smyčku REPL, správce projektů apod. A když už mluvíme o překladači: jednalo se o jeden z prvních překladačů se skutečně „lidskými“ chybovými hlášeními, která v závislosti na kontextu obsahují i návod, jak chybu opravit (což dnes již není tak překvapivé a revoluční, ovšem před šesti lety to byla ukázka nového stylu).

Jazyk Elm vs primární funkce JavaScriptových frameworků pro front end

Ve světě JavaScriptu vzniklo velké množství různých frameworků určených pro tvorbu grafického uživatelského rozhraní (front end). Tyto frameworky jsou mnohdy interně velmi komplikované a nabízí vývojářům velké množství různých funkcí popř. komponent. Ovšem když se zamyslíme nad důvody existence těchto frameworků, je možné (s jistou, ale docela malou mírou nadsázky) tvrdit, že primárním účelem těchto frameworků je zajištění konzistence a synchronizace mezi vnitřním stavem aplikace na straně jedné a grafickým uživatelským rozhraním na straně druhé. Toho lze dosáhnout různými způsoby; od vlastně explicitní implementace synchronizace (API postavené na JSONu a RESTu) až po různé technologie pro konstrukci DOMu z dat.

Zajímavé je, že programovací jazyk Elm tuto důležitou funkcionalitu implementuje přímo jako součást jazyka, protože nabízí mechanismus nazvaný Model, View, Update. Podrobnosti si ukážeme v samostatném článku, protože se jedná o důležité téma. Výsledkem je, že i když Elm přímo slouží pro tvorbu uživatelského rozhraní, není nutné, aby pro něj vznikaly různé UI frameworky, protože jazyk sám nabízí potřebnou funkcionalitu.

Poznámka: ostatně není bez zajímavosti, že JavaScriptové frameworky Redux, Vuex či Zustand (pro Redux) jsou postaveny na myšlenkách Elmu.

Je Elm mrtvým jazykem, který se dále nevyvíjí?

„Old programming languages don’t die. Developers just get bored.“

Když přejdeme na stránky s Git repositářem překladače jazyka Elm nebo (možná ještě lépe) na stránku se seznamem oficiálně vydaných verzí, zjistíme, že se tento programovací jazyk vlastně prakticky vůbec dále nevyvíjí. Poslední oficiálně vydaná verze totiž nese číslo 0.19.1 a vydána byla už před sedmi (!) lety. To je v poměrně ostrém kontrastu s některými dalšími technologiemi, které se v informatice používají a u nichž platí, že pokud nebyla tento týden vydána nová verze (či alespoň oprava CVE), popř. pokud si autoři nějakého balíčku „dovolí“ vzít si krátkou dovolenou, považuje se to za téměř katastrofu.

Na „zakonzervování“ stavu Elmu se můžeme dívat z několika pohledů. Některé z nich byly zmíněny v článku o způsobech zajištění zpětné kompatibility v jazyku Go, který (zcela náhodou) na Rootu vyšel minulý týden. Jeden pohled říká, že technologie, která se přestane vyvíjet, je mrtvou technologií. Druhý pohled naopak poukazuje na existenci stabilních a stále používaných řešení postavených na COBOLu, FORTRANU 77 (ano, to je doba, kdy se ještě psal verzálkami), Fortranu 90, ANSI C, C99 atd. Nutno dodat, že některá řešení se prostě nevyplatí přepsat do modernějších jazyků. Elm můžeme z pohledu sémantiky považovat za jazyk, který nemá nutnost se dále vyvíjet, protože (zdá se) již obsahuje všechny důležité vlastnosti. U jiných jazyků tomu tak není – příkladem je Go, do kterého byly později přidány generické datové typy, neustále se diskutuje o způsobech zpracování chyb atd.

Poznámka: některé důvody vedoucí k tomuto stavu byly nastíněny v následujícím rozhovoru: Elm & The Future of Open Source (with Evan Czaplicki).

Nechtěný důsledek: přesnější odpovědi získávané z velkých jazykových modelů

Fakt, že se programovací jazyk Elm už přes šest let nachází v „zamrzlé“ fázi, má jeden zajímavý nechtěný (vlastně velmi pozitivní) důsledek: velké jazykové modely (LLM) většinou jazyk Elm dobře rozpoznávají a jejich odpovědi jsou přesné a platné pro jeho poslední verzi. Navíc jsou odpovědi jednoznačné i díky tomu, že Elm je jak programovací jazyk, tak i de facto svým způsobem front endový framework. Tj. otázky typu „jak vytvořit tlačítko zvyšující hodnotu o jedničku“ mají vždy jedinou jednoznačnou a v čase stabilní odpověď (která by v případě jiných ekosystémů byla do značné míry závislá jak na konkrétní verzi programovacího jazyka, tak i na použitém frameworku). To tedy znamená, že jazyk, který byl (prozatím) stabilizován již v roce 2019, velmi dobře zapadá do současného IT světa, kterému (zdá se) začínají do značné míry vládnout jazykové modely a na nich postavení agenti.

Instalace interpretru a překladače jazyka Elm

V případě, že striktně nevyžadujete překlad Elmu ze zdrojových kódů (přes ghc), je instalace Elmu až triviálně jednoduchá. Nejdříve se stáhne zazipovaný spustitelný soubor obsahující všechny potřebné nástroje:

$ wget https://github.com/elm/compiler/releases/download/0.19.1/binary-for-linux-64-bit.gz

Ve druhém kroku se za(g)zipovaný soubor rozbalí:

$ gunzip binary-for-linux-64-bit.gz

Výsledek:

$ ls -la -h binary-for-linux-64-bit
-rw-r--r--. 1 ptisnovs ptisnovs 28M Dec  8  2021 binary-for-linux-64-bit
Poznámka: 28MB je relativně značná velikost (tolik kdysi míval celý GCC), ovšem k dispozici získáme překladač, REPL, správce balíčků, nápovědu atd.

Otestujeme spuštěním získané „binárky“:

Hi, thank you for trying out Elm 0.19.1. I hope you like it!
 
-------------------------------------------------------------------------------
I highly recommend working through <https://guide.elm-lang.org> to get started.
It teaches many important concepts, including how to use `elm` in the terminal.
-------------------------------------------------------------------------------
 
The most common commands are:
 
    binary-for-linux-64-bit repl
        Open up an interactive programming session. Type in Elm expressions like
        (2 + 2) or (String.length "test") and see if they equal four!
 
    binary-for-linux-64-bit init
        Start an Elm project. It creates a starter elm.json file and provides a
        link explaining what to do from there.
 
    binary-for-linux-64-bit reactor
        Compile code with a click. It opens a file viewer in your browser, and
        when you click on an Elm file, it compiles and you see the result.
 
There are a bunch of other commands as well though. Here is a full list:
 
    binary-for-linux-64-bit repl    --help
    binary-for-linux-64-bit init    --help
    binary-for-linux-64-bit reactor --help
    binary-for-linux-64-bit make    --help
    binary-for-linux-64-bit install --help
    binary-for-linux-64-bit bump    --help
    binary-for-linux-64-bit diff    --help
    binary-for-linux-64-bit publish --help
 
Adding the --help flag gives a bunch of additional details about each one.
 
Be sure to ask on the Elm slack if you run into trouble! Folks are friendly and
happy to help out. They hang out there because it is fun, so be kind to get the
best results!

Použití interaktivní smyčky REPL

Výhody překladače, resp. přesněji řečeno překladače programovacího jazyka se silným typovým systémem (a do této kategorie Elm nepochybně patří), jsou pravděpodobně většině vývojářů zřejmé – výsledkem bývá vyšší rychlost běhu aplikací, obecně menší paměťové nároky procesů, na cílovém počítači nemusí být nainstalován žádný interpret a v neposlední řadě je poměrně velká část chyb (bohužel spíše těch triviálních) objevena již překladačem a nikoli v době běhu programu u uživatele nebo dokonce zákazníka.

Nicméně existují oblasti, v nichž se prosadil dosti odlišný způsob vývoje, který je založen na přímé interakci (resp. dialogu) mezi uživatelem a počítačem. V tom nejjednodušším (ale mnohdy velmi užitečném) případě se jedná o systémy vybavené interaktivní smyčkou REPL (Read Eval Print Loop), jejichž poněkud primitivní podobu si někteří mohou pamatovat z dob osmibitových mikropočítačů a interpretrů jazyka BASIC. Nicméně klasický REPL najdeme například i v Pythonu a dalších moderních skriptovacích jazycích (pro Python navíc existují různá jeho rozšíření, například v podobě IPythonu). V současnosti se mnohdy původní REPL nahrazuje spíše rozhraním ve stylu diáře (notebooku). Příkladem je projekt Jupyter Notebook, který v současnosti podporuje velké množství skriptovacích jazyků. A klasický REPL je dnes do jisté míry suplován i systémy s AI chaty (vibe coding apod. jako kontrast ke spec codingu).

Překladač jazyka Elm je vybaven plnohodnotnou interaktivní smyčkou REPL, která se inicializuje následujícím příkazem:

$ ./binary-for-linux-64-bit repl
 
---- Elm 0.19.1 ----------------------------------------------------------------
Say :help for help and :exit to exit! More at <https://elm-lang.org/0.19.1/repl>
--------------------------------------------------------------------------------
>
Poznámka: mimochodem – v této chvíli si pravděpodobně většina vývojářů vytvoří symlink nazvaný elm nebo přímo přejmenuje binary-for-linux-64-bit na elm.

Interakce uživatele s Elmem může vypadat takto:

---- Elm 0.19.1 ----------------------------------------------------------------
Say :help for help and :exit to exit! More at <https://elm-lang.org/0.19.1/repl>
--------------------------------------------------------------------------------
 
> :help
Valid commands include:
 
  :exit    Exit the REPL
  :help    Show this information
  :reset   Clear all previous imports and definitions
 
More info at <https://elm-lang.org/0.19.1/repl>
 
> 6*7
42 : number
 
> 6.0*7.0
42 : Float
 
> :quit

Klávesové zkratky použitelné v REPLu

Jednou z důležitých vlastností (pro každodenní práci) je velké množství klávesových zkratek, které REPL programovacího jazyka Elm podporuje. Tyto zkratky jsou do značné míry odvozeny od GNU Readline a proto jsou v této kapitole vypsány vybrané klávesové zkratky, jenž jsou ve výchozím nastavení použity právě knihovnou GNU Readline při přepnutí do režimu Emacs. Tyto klávesové zkratky lze využít i v interaktivní smyčce REPL Elmu (což bylo pochopitelně otestováno).

Příkazy pro přesuny kurzoru

Základní příkazy pro přesun kurzoru používají klávesové kombinace Ctrl+znak, Alt+znak popř. alternativně Esc, znak v případě, že zkratky Alt+znak kolidují s emulátorem terminálu (například vyvolávají příkazy z menu). V případě, že je terminál správně nakonfigurován, měly by fungovat i kurzorové šipky a navíc i klávesy Home a End (se zřejmou funkcí):

Klávesa Význam
Ctrl+B přesun kurzoru na předchozí znak
Ctrl+F přesun kurzoru na další znak
   
Alt+B přesun kurzoru na předchozí slovo
Alt+F přesun kurzoru na následující slovo
Esc, B shodné s Alt+B
Esc, F shodné s Alt+F
   
Ctrl+A přesun kurzoru na začátek řádku
Ctrl+E přesun kurzoru na konec řádku

Mazání textu, práce s kill ringem

Pro přesun části textu v rámci editovaného řádku s programovým kódem se používá takzvaný kill ring (to je termín převzatý z Emacsu), do něhož se smazaný text uloží. Pro vložení takto smazaného textu do jiné oblasti se používá operace nazvaná yank (odpovídá paste). Některé dále uvedené příkazy dokážou s kill ringem pracovat (asi nejčastější jsou kombinace Ctrl+K a Ctrl+Y):

Klávesa Význam
Ctrl+K smaže text od kurzoru do konce řádku a uloží ho do kill ringu
Ctrl+U smaže text od začátku řádku do pozice kurzoru a uloží ho do kill ringu
Ctrl+W smaže předchozí slovo a uloží ho do kill ringu
Alt+D smaže následující slovo a uloží ho do kill ringu
   
Ctrl+Y vloží text z kill ringu na místo, na němž se nachází kurzor (yank)
Alt+Y po operaci Ctrl+Y dokáže rotovat historií kill ringu a obnovit tak (před)předchozí smazaný text
   
Ctrl+D smaže jeden znak (pokud je ovšem na řádku nějaký obsah, jinak typicky ukončí aplikaci)

Práce s historií dříve zadaných příkazů

Z této skupiny příkazů je pravděpodobně nejznámější klávesová zkratka Ctrl+R, která slouží pro vyhledávání předchozích příkazů v historii:

Klávesa Význam
Ctrl+P průchod historií – předchozí text
Ctrl+N průchod historií – následující text
Ctrl+R zpětné (interaktivní) vyhledávání v historii
Ctrl+G ukončení režimu vyhledávání

Některé další dostupné příkazy

A na závěr si uveďme některé další více či méně užitečné klávesové zkratky (z nějakého důvodu používám Ctrl+T častěji, než by možná bylo zdrávo):

Klávesa Význam
Tab implicitní klávesa pro zavolání completeru
Ctrl+T prohození dvou znaků (před kurzorem a na pozici kurzoru)
   
Alt+U text od pozice kurzoru do konce slova se změní NA VERZÁLKY
Alt+L text od pozice kurzoru do konce slova se změní na mínusky
Alt+C text od pozice kurzoru do konce slova se změní Tak, Že Slova Začínají Velkým Písmenem

Uživatelsky příjemná chybová hlášení překladače a interpretru

„Writing proper error messages is an art that every software developer should master.“

Jednou z nejpraktičtějších vlastností jazyka Elm jsou velmi čitelná chybová hlášení překladače. Při nalezení chyby se totiž vypíše nejenom informace o tom, k jaké chybě došlo, ale i v jakém kontextu byla chyba nalezena a taktéž návod, jak lze chybu napravit (ovšem pochopitelně není možné, aby byl překladač na sto procent úspěšný). Tento koncept je v oblasti IT relativně nový, protože několik desítek let (cca od padesátých let minulého století přibližně do roku 2012) bývala chybová hlášení překladačů velmi strohá a především – jednalo se skutečně o chybová hlášení a nikoli o snahu překladače naučit programátora korektnímu způsobu zápisu programů:

foo.map(1): Error: ':' expected
foo.map(1): Error: Unexpected trailing garbage characters
foo.map(3): Error: '.O' is not a recognized control command
foo.map(4): Error: ':' expected
foo.map(14): Error: Symbol 'AUTOSTRT' is already defined
foo.map(14): Error: ':' expected
foo.map(14): Error: Symbol '.size' is already defined
foo.map(15): Error: Symbol 'EXEHDR' is already defined
foo.map(15): Error: ':' expected
foo.map(15): Error: Symbol '.size' is already defined
foo.map(15): Error: Unexpected trailing garbage characters
foo.map(16): Error: Symbol 'CODE' is already defined
foo.map(16): Error: ':' expected

nebo:

1.c:1:3: error: expected declaration specifiers or ‘...’ before ‘;’ token
1.c:1:1: error: return type defaults to ‘int’ [-Wimplicit-int]
1.c: In function ‘m’:
1.c:1:6: error: stray ‘@’ in program
1.c:1:7: error: expected expression before ‘,’ token
1.c:1:8: error: ‘x’ undeclared (first use in this function)
1.c:1:8: note: each undeclared identifier is reported only once for each function it appears in
1.c:1:7: warning: left-hand operand of comma expression has no effect [-Wunused-value]
1.c: At top level:
1.c:1:10: error: expected identifier or ‘(’ before numeric constant
1.c: In function ‘m’:
1.c:1:9: warning: control reaches end of non-void function [-Wreturn-type]

Tento přístup změnil právě jazyk Elm a po něm i Rust či TypeScript (kupodivu Go v tomto ohledu poněkud zaostává). Naopak se poněkud zlepšila chybová hlášení céčkových překladačů, takže se předchozí chybová hlášení nyní zobrazují odlišně:

1.c:1:3: error: expected declaration specifiers or ‘...’ before ‘;’ token
    1 | m(;){@,x}2
      |   ^
1.c:1:1: error: return type defaults to ‘int’ [-Wimplicit-int]
    1 | m(;){@,x}2
      | ^
1.c: In function ‘m’:
1.c:1:6: error: stray ‘@’ in program
    1 | m(;){@,x}2
      |      ^
1.c:1:7: error: expected expression before ‘,’ token
    1 | m(;){@,x}2
      |       ^
1.c:1:8: error: ‘x’ undeclared (first use in this function)
    1 | m(;){@,x}2
      |        ^
1.c:1:8: note: each undeclared identifier is reported only once for each function it appears in
1.c:1:7: warning: left-hand operand of comma expression has no effect [-Wunused-value]
    1 | m(;){@,x}2
      |       ^
1.c: At top level:
1.c:1:10: error: expected identifier or ‘(’ before numeric constant
    1 | m(;){@,x}2
      |          ^
1.c: In function ‘m’:
1.c:1:9: warning: control reaches end of non-void function [-Wreturn-type]
    1 | m(;){@,x}2
      |         ^

Ukažme si několik příkladů chybových hlášení získaných přímo z REPLu jazyka Elm:

---- Elm 0.19.1 ----------------------------------------------------------------
Say :help for help and :exit to exit! More at <https://elm-lang.org/0.19.1/repl>
--------------------------------------------------------------------------------
 
> 42
42 : number
 
> "foo"
"foo" : String
 
> 42+"foo"
-- TYPE MISMATCH ---------------------------------------------------------- REPL
 
I cannot do addition with String values like this one:
 
3|   42+"foo"
        ^^^^^
The (+) operator only works with Int and Float values.
 
Hint: Switch to the (++) operator to append strings!
 
> 42++"foo"
-- TYPE MISMATCH ---------------------------------------------------------- REPL
 
The (++) operator can append List and String values, but not number values like
this:
 
3|   42++"foo"
     ^^
Try using String.fromInt to turn it into a string? Or put it in [] to make it a
list? Or switch to the (::) operator?
 
> String.fromInt(42)++"foo"
"42foo" : String

Konečně jsme dospěli ke správné variantě :-)

> nil
-- NAMING ERROR ----------------------------------------------------------- REPL
 
I cannot find a `nil` variable:
 
3|   nil
     ^^^
These names seem close though:
 
    min
    not
    pi
    sin
 
Hint: Read <https://elm-lang.org/0.19.1/imports> to see how `import`
declarations work in Elm.

Co může být lepšího, když chybové hlášení není jen „buzerací“ vývojáře (nepříjemné vzpomínky na Pascal), ale hlavně výukovým materiálem?:

> x=42
42 : number
 
> x=x+1
-- CYCLIC DEFINITION ------------------------------------------------------ REPL
 
The `x` value is defined directly in terms of itself, causing an infinite loop.
 
2| x=x+1
   ^
Are you are trying to mutate a variable? Elm does not have mutation, so when I
see x defined in terms of x, I treat it as a recursive definition. Try giving
the new value a new name!
 
Maybe you DO want a recursive value? To define x we need to know what x is, so
let’s expand it. Wait, but now we need to know what x is, so let’s expand it...
This will keep going infinitely!
 
Hint: The root problem is often a typo in some variable name, but I recommend
reading <https://elm-lang.org/0.19.1/bad-recursion> for more detailed advice,
especially if you actually do need a recursive value.

Pokusme se překladač zmást – on to klidně přizná:

-- UNEXPECTED SYMBOL ------------------------------------------------------ REPL
 
I was not expecting to run into the "has type" symbol here:
 
3|   42: int
       ^
Maybe you want :: instead? To put something on the front of a list?
 
Note: The single colon is reserved for type annotations and record types, but I
think I am parsing the definition of `repl_input_value_` right now.
 
Note: I may be getting confused by your indentation. Is this supposed to be part
of a type annotation AFTER the `repl_input_value_` definition? If so, the
problem may be a bit before the "has type" symbol. I need all definitions to be
exactly aligned (with exactly the same indentation) so the problem may be that
this new definition is indented a bit too much.

Typový systém programovacího jazyka Elm

„Testing is good, impossible is better“

S některými datovými typy, které jsou jazykem Elm podporovány, jsme se (vlastně trošku mimochodem) setkali v předchozích kapitolách. Ovšem pro navazující články o Elm je nutné zmínit všechny podporované datové typy.

První datový typ se jmenuje unit, ovšem většinou se mu říká „null type“. Je reprezentován prázdnými kulatými závorkami a technicky se jedná o n-tici bez prvků:

> x=()
() : ()
Poznámka: tento datový typ je v praxi velmi užitečný. Podobným typem známým z céčkovské větve jazyků je typ void, jehož jméno ovšem (chybně?) naznačuje, že neexistuje žádný prvek tohoto typu.

Dalším datovým typem je typ bool. Ten již není, na rozdíl od typu unit nijak výjimečný. Obsahuje dvě hodnoty true a false:

> a=True
True : Bool
 
> b=False
False : Bool

Numerické datové typy jsou představovány obecnými čísly typu number, který se dále rozpadá na celá čísla Int a hodnoty s plovoucí řádovou čárkou Float (pozor: zde se Elm odlišuje od SML apod.):

> x = 42
42 : number
 
> z = 1.5
1.5 : Float

Proměnnou typu Int je většinou nutné explicitně definovat. Povšimněte si, že určení typu proměnné a následné přiřazení je v REPLu zapsáno třemi příkazy:

> y : Int
| y = 42
|   
42 : Int

Některé operace ovšem dokážou produkovat přímo hodnotu typu Int – viz rozdíl mezi dvojicí operací podílu:

> 7/2
3.5 : Float
 
> 7//2
3 : Int

Popř. též:

> round(7/2)
4 : Int

Protože typ funkce round vypadá takto:

> round
<function> : Float -> Int

Následují řetězce, neboli typ string:

> msg="Hello world!"
"Hello world!" : String

Řetězce mohou být i víceřádkové. Jejich zápis vypadá následovně:

> lorem_ipsum =
|   """
|   Lorem ipsum dolor sit amet, consectetur
|   adipiscing elit, sed do eiusmod tempor
|   incididunt ut labore et dolore magna
|   aliqua. Ut enim ad minim veniam, quis
|   nostrud exercitation ullamco laboris
|   nisi ut aliquip ex ea commodo consequat.
|   Duis aute irure dolor in reprehenderit
|   in voluptate velit esse cillum dolore eu
|   fugiat nulla pariatur. Excepteur sint
|   occaecat cupidatat non proident, sunt in
|   culpa qui officia deserunt mollit anim
|   id est laborum.
|   """
"\n  Lorem ipsum dolor sit amet, consectetur\n  adipiscing elit, sed do eiusmod
tempor\n  incididunt ut labore et dolore magna\n  aliqua. Ut enim ad minim
veniam, quis\n  nostrud exercitation ullamco laboris\n  nisi ut aliquip ex ea
commodo consequat.\n  Duis aute irure dolor in reprehenderit\n  in voluptate
velit esse cillum dolore eu\n  fugiat nulla pariatur. Excepteur sint\n
occaecat cupidatat non proident, sunt in\n  culpa qui officia deserunt mollit
anim\n  id est laborum.\n  "
    : String

A konečně typ char reprezentujíje jediný znak:

> c='?'
'?' : Char

Složené datové typy

V Elmu jsou podporovány tři složené datové typy: n-tice (Tuple), záznamy (Record) a seznamy (List). K nim se předávají ještě typy Maybe, Result, Dict a Set, které si popíšeme příště (společně s popisem záznamů).

Nejjednodušší jsou n-tice, které mohou obsahovat prvky libovolných typů. Typ n-tice jako celku je pak odvozen od typů jednotlivých prvků. Speciálním případem je n-tice bez prvků, neboli typ unit zmíněný v předchozí kapitole:

> x=()
() : ()

Následuje příklad n-tic s větším množstvím prvků. Povšimněte si toho, jak je zapsán datový typ takové n-tice:

> (1, 2, 3)
(1,2,3) : ( number, number1, number2 )
 
> ("foo", "bar", "baz")
("foo","bar","baz") : ( String, String, String )
 
> ("answer", 42)

n-tice obsahující jiné n-tice:

> (1, (2, (3, 4)))
(1,(2,(3,4)))
    : ( number, ( number1, ( number2, number3 ) ) )

Ovšem REPL z praktických důvodů neumožňuje konstrukci větších n-tic:

> (1, 2, 3, 4)
-- BAD TUPLE -------------------------------------------------------------- REPL
 
I only accept tuples with two or three items. This has too many:
 
5|   (1, 2, 3, 4)
     ^^^^^^^^^^^^
I recommend switching to records. Each item will be named, and you can use the
`point.x` syntax to access them.
 
Note: Read <https://elm-lang.org/0.19.1/tuples> for more comprehensive advice on
working with large chunks of data in Elm.
Poznámka: k důvodům se ještě později vrátíme.

Vzhledem k tomu, že n-tice s jediným prvkem nemá praktický význam, není podporována (na rozdíl od Pythonu, kde se však jedná o syntakticky problematický rys jazyka):

> (1)
1 : number
 
> (1,)
|
-- MISSING EXPRESSION ----------------------------------------------------- REPL
 
I am partway through parsing some parentheses, but I got stuck here:
 
5|   (1,)
        ^
I was expecting to see an expression like 42 or "hello". Once there is something
there, I can probably give a more specific hint!
 
Note: This can also happen if run into reserved words like `let` or `as`
unexpectedly. Or if I run into operators in unexpected spots. Point is, there
are a couple ways I can get confused and give sort of weird advice!

A konečně, nejdůležitějším základním složeným datovým typem jsou seznamy (lists). Ty jsou homogenní, tj. všechny prvky seznamů musí být stejného typu:

> [1, 2, 3]
[1,2,3] : List number

Pokus o vytvoření heterogenního seznamu skončí s chybou:

> [1, "foo", True]
-- TYPE MISMATCH ---------------------------------------------------------- REPL
 
The 2nd element of this list does not match all the previous elements:
 
5|   [1, "foo", True]
         ^^^^^
The 2nd element is a string of type:
 
    String
 
But all the previous elements in the list are:
 
    number
 
Hint: Everything in a list must be the same type of value. This way, we never
run into unexpected values partway through a List.map, List.foldl, etc. Read
<https://elm-lang.org/0.19.1/custom-types> to learn how to “mix” types.
 
Hint: Try using String.toInt to convert it to an integer?

Víme již, že speciálním případem n-tice je n-tice bez prvků. I u seznamů se jedná o speciální případ, o čemž se můžeme velmi snadno přesvědčit (viz typ výrazu):

> []
[] : List a
Poznámka: o speciální případ se zde jedná z toho důvodu, že Elm 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.

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

  • buď je seznam prázdný
  • nebo má formu hlava::tělo, kde hlava je první prvek seznamu

Příklad:

> 1::[2,3]
[1,2,3] : List number

To například znamená, že seznam [42] je shodný se seznamem 42::[]:

> [42]
[42] : List number
> 42::[]
[42] : List number

Zápis hlava::tělo se používá jak pro konstrukci seznamu, tak i například ve vzorech (patterns), s nimiž se seznámíme později.

Standardní operátory, priorita a asociativita operátorů

V následující tabulce jsou vypsány všechny standardní operátory programovacího jazyka Elm. Tyto operátory se od sebe liší (pochopitelně) nejenom prováděnou operací, ale taktéž prioritou a asociativitou. Priorita určuje, v jakém pořadí se budou operátory vyhodnocovat, pokud jsou použity v jediném výrazu (například ve výrazu 1+2*3). A asociativita určuje uzávorkování operátorů se stejnou prioritou, tj. zda se provede (1+2)+3 nebo naopak 1+(2+3). Z tabulky je patrné, že některé operátory známé z jiných programovacích jazyků jsou asociativní zleva, ovšem skupina několika operátorů má asociativitu zprava:

Operátor Priorita Asociativita Stručný popis
>> 9 zleva kompozice funkcí
<< 9 zprava kompozice funkcí
^ 8 zprava operace umocnění
* / // % rem 7 zleva součin, podíl, zbytek po dělení
+ – 6 zleva součet a rozdíl
++ :: 5 zprava spojení řetězců a seznamů, přidání prvku do seznamu
== /= < > <= >= 4 × relační operace
&& 3 zprava logická spojka „a“
|| 2 zprava logická spojka „nebo“
|> 0 zleva operátor kolony (zřetězení volání funkcí)
<| 0 zprava volání funkce, ovšem díky prioritě lze většinou vynechat závorky
Poznámka: pozor na to, že některé operátory mají odlišný význam v porovnání s dalšími jazyky z rodiny ML. Týká se to například operátoru ^. A navíc jsou některé symboly neobsazeny, například @, čehož taktéž později využijeme.

Poněkud sice předbíháme, ale už nyní si můžeme uvést, že standardní operátory jsou definovány následujícím způsobem (jsou tedy navázány na funkce, jejichž jména jsou uvedena v pravém sloupci):

infix right 0 (<|) = apL
infix left  0 (|>) = apR
infix right 2 (||) = or
infix right 3 (&&) = and
infix non   4 (==) = eq
infix non   4 (/=) = neq
infix non   4 (<)  = lt
infix non   4 (>)  = gt
infix non   4 (<=) = le
infix non   4 (>=) = ge
infix right 5 (++) = append
infix left  6 (+)  = add
infix left  6 (-)  = sub
infix left  7 (*)  = mul
infix left  7 (/)  = fdiv
infix left  7 (//) = idiv
infix right 8 (^)  = pow
infix left  9 (<<) = composeL
infix right 9 (>>) = composeR

Definice funkcí a typová inference

Definice funkcí je zapsána poměrně přímočarým způsobem na jednom programovém řádku nebo na více řádcích (pochopitelně v závislosti na komplikovanosti těla funkce). V případě, že je funkce tvořena jediným výrazem, což je i případ funkce inc, lze ji zapsat na jeden řádek:

> inc x = x + 1
<function> : number -> number

Nic nám ovšem nebrání v zápisu funkce na více řádcích. Ukončení těla funkce v REPLu zajistí prázdný řádek (stisk Enteru):

> int x =
|   x+1
|
 
<function> : number -> number

Povšimněte si, že díky typové inferenci byl korektně odvozen typ parametru funkce i typ návratové hodnoty. Ovšem taktéž je možné typ funkce určit explicitně. Poté se (opět v REPLu) nejprve zapíše hlavička funkce i se všemi typy (parametrů a návratové hodnoty) a na řádku dalším pak vlastní implementace funkce:

> inc : Int -> Int
| inc x = x + 1
|
<function> : Int -> Int

Dtto, ale pro funkci s tělem rozepsaným na samostatném řádku:

> inc : Int -> Int
| inc x =
|   x + 1
|
 
<function> : Int -> Int
Poznámka: záleží na vývojáři, zda preferuje využití typové inference (kde je to možné) či zda bude chtít explicitně zapisovat všechny typy. Oba způsoby mají své klady a zápory.

Vlastní zavolání funkce je již triviální. Povšimněte si, že jsou prováděny i typové kontroly:

> inc 42
43 : Int
 
> inc 3.14
-- TYPE MISMATCH ---------------------------------------------------------- REPL
 
The 1st argument to `inc` is not what I expect:
 
7|   inc 3.14
         ^^^^
This argument is a float of type:
 
    Float
 
But `inc` needs the 1st argument to be:
 
    Int
 
Note: Read <https://elm-lang.org/0.19.1/implicit-casts> to learn why Elm does
not implicitly convert Ints to Floats. Use toFloat and round to do explicit
conversions.

Funkce s větším počtem parametrů

Zajímavější bude zjistit, jak se definují a volají funkce s větším počtem parametrů. To si ostatně opět můžeme velmi snadno otestovat, a to například na funkci s realizací součtu. Jednořádková varianta založená na typové inferenci:

> add x y = x + y
<function> : number -> number -> number
 
> add 3 4
7 : number

Varianta zapsaná na více řádků:

> add x y =
|   x + y
|
<function> : number -> number -> number
 
> add 3 4
7 : number
Poznámka: typ funkce add může být zpočátku matoucí. Původní inc měla typ number → number, tedy jednalo se vlastně o zobrazení „číslo na číslo“. U funkce add je typ odvozen na number → number → number

, což vlastně znamená „funkce akceptující číslo a vracející jinou funkci, která zobrazuje číslo na (jiné) číslo“. Tento způsob zápisu je v některých funkcionálních jazycích poměrně často používán a dá se na něj rychle zvyknout. A zápis typu se dá i ověřit:

> add 1
<function> : number -> number

Předáním jednoho parametru jsme skutečně získali funkci realizující zobrazení „číslo na číslo“.

Samozřejmě můžeme explicitně zapsat i typy parametrů funkce a typ návratové hodnoty. Musíme pouze dodržet stejný způsob zápisu „šipek“, jako je tomu u výsledku typové inference:

> add : Int -> Int -> Int
| add x y = x + y
|
<function> : Int -> Int -> Int

Příklady typových definic standardních funkcí

Podívejme se na několik příkladů typových definic funkcí dostupných ve standardní knihovně programovacího jazyka Elm. Všechny definice prozkoumáme přímo z REPLu, čímž ověříme jak samotnou existenci funkce, tak i typ jejích parametrů i typ návratové hodnoty. Povšimněte si, jak popisná je dvojice jméno_funkce + typy; většinou ani není vyžadována další podrobnější dokumentace:

> abs
<function> : number -> number
 
> sqrt
<function> : Float -> Float

Převody mezi typem Float a Int vyžadují nějakou formu manipulace s ciframi za desetinnou čárkou:

> floor
<function> : Float -> Int
 
> ceiling
<function> : Float -> Int
 
> round
<function> : Float -> Int

Opačný převod je nutný kvůli silným typovým kontrolám:

> toFloat
<function> : Int -> Float

Manipulace s řetězci, kde vstupem i výstupem je řetězec:

> String.toUpper
<function> : String -> String
 
> String.toLower
<function> : String -> String
 
> String.trim
<function> : String -> String

Testy na obsah řetězce:

Školení Kubernetes

> String.startsWith
<function> : String -> String -> Bool
 
> String.endsWith
<function> : String -> String -> Bool
 
> String.contains
<function> : String -> String -> Bool

Další funkce, jimiž prováděné operace by měly být zřejmé z uvedeného jména i typů:

> String.length
<function> : String -> Int
 
> String.concat
<function> : List String -> String
 
> String.split
<function> : String -> String -> List String

Obsah navazujícího článku

V navazujícím článku o programovacím jazyku Elm se budeme věnovat dvěma důležitým tématům. Prvním z nich je využití strukturovaných datových typů, a to včetně práce s typem Result atd. A druhé téma se věnuje pattern matchingu, jenž je v Elmu používán ve spojitosti s různými datovými typy (v Elmu a dalších programovacích jazycích pocházejících z rodiny ML jsou tyto dvě vlastnosti jazyka úzce svázány, kdežto například v Pythonu tomu tak není).

Literatura

Poznámka: v této kapitole jsou uvedeny nejenom knihy o jazyku ML resp. většinou o Standard ML, ale i knihy o programovacím jazyku OCaml, který ze Standard ML ze značné míry vychází. A samozřejmě byly přidány knihy, které se týkají programovacího jazyka Elm a jeho způsobech použití při tvorbě front endu:
  1. Beginning Elm
    https://elmprogramming.com/
  2. Elm in Action
    https://www.manning.com/books/elm-in-action
  3. Programming Language Fundamentals: A Metalanguage Approach in Elm
    https://books.google.cz/bo­oks/about/Programming_Lan­guage_Fundamentals.html?id=OR­H9EAAAQBAJ
  4. Programming Elm: Build Safe and Maintainable Front-End Applications
    https://www.goodreads.com/bo­ok/show/37824829-programming-elm
  5. Web Applications with Elm: Functional Programming for the Web
    https://www.goodreads.com/bo­ok/show/33160729-web-applications-with-elm
  6. ML for the Working Programmer
    https://www.cl.cam.ac.uk/~lp15/MLbo­ok/pub-details.html
  7. Elements of ML Programming, 2nd Edition (ML97)
    http://infolab.stanford.e­du/~ullman/emlp.html
  8. A tour of Standard ML
    https://saityi.github.io/sml-tour/tour/welcome
  9. The History of Standard ML
    https://smlfamily.github.i­o/history/SML-history.pdf
  10. The Standard ML Basis Library
    https://smlfamily.github.io/Basis/
  11. Programming in Standard ML
    http://www.cs.cmu.edu/~rwh/is­ml/book.pdf
  12. Programming in Standard ML '97: A Tutorial Introduction
    http://www.lfcs.inf.ed.ac­.uk/reports/97/ECS-LFCS-97–364/
  13. Programming in Standard ML '97: An On-line Tutorial
    https://homepages.inf.ed.ac­.uk/stg/NOTES/
  14. The OCaml system release 4.13
    https://ocaml.org/releases/4­.13/htmlman/index.html
  15. Real World OCaml: Functional programming for the masses
    https://dev.realworldocaml.org/
  16. OCaml from the Very Beginning
    http://ocaml-book.com/
  17. OCaml from the Very Beginning: More OCaml : Algorithms, Methods & Diversions
    http://ocaml-book.com/more-ocaml-algorithms-methods-diversions/
  18. Unix system programming in OCaml
    http://ocaml.github.io/ocamlunix/
  19. OCaml for Scientists
    https://www.ffconsultancy­.com/products/ocaml_for_sci­entists/index.html
  20. Using, Understanding, and Unraveling The OCaml Language
    https://caml.inria.fr/pub/docs/u3-ocaml/
  21. Developing Applications With objective Caml
    https://caml.inria.fr/pub/docs/oreilly-book/index.html
  22. Introduction to Objective Caml
    http://courses.cms.caltech­.edu/cs134/cs134b/book.pdf
  23. How to Think Like a (Functional) Programmer
    https://greenteapress.com/thin­kocaml/index.html
  24. Types and Programming Languages
    https://i.warosu.org/data/sci/im­g/0163/64/1725651701869705­.pdf
  25. Purely Functional Data Structures (Chris Okasaki)
    https://www.cs.cmu.edu/~rwh/stu­dents/okasaki.pdf

Předchozí články o jazyku ML/SML i o jazycích OCaml a F#

  1. ML – funkcionální jazyk s revolučním typovým systémem
    https://www.root.cz/clanky/ml-funkcionalni-jazyk-s-revolucnim-typovym-systemem/
  2. Funkce a typový systém programovacího jazyka ML
    https://www.root.cz/clanky/funkce-a-typovy-system-programovaciho-jazyka-ml/
  3. 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/
  4. Funkcionální programovací jazyk F#
    https://www.root.cz/clanky/fun­kcionalni-programovaci-jazyk-f/
  5. Programovací jazyk OCaml
    https://www.root.cz/clanky/pro­gramovaci-jazyk-ocaml/
  6. Programovací jazyk F#: proměnné, funkce a datové typy
    https://www.root.cz/clanky/pro­gramovaci-jazyk-f-promenne-funkce-a-datove-typy/
  7. Proměnné, funkce a datové typy v jazyku OCaml
    https://www.root.cz/clanky/promenne-funkce-a-datove-typy-v-jazyku-ocaml/
  8. Rekurze a pattern matching v programovacím jazyku F#
    https://www.root.cz/clanky/rekurze-a-pattern-matching-v-programovacim-jazyku-f/
  9. Práce se seznamy v jazyce F#
    https://www.root.cz/clanky/prace-se-seznamy-v-jazyce-f/
  10. Programovací jazyk OCaml: rekurze, pattern matching a práce se seznamy
    https://www.root.cz/clanky/pro­gramovaci-jazyk-ocaml-rekurze-pattern-matching-a-prace-se-seznamy/
  11. Datové typy Option, Result a Array v programovacím jazyku F#
    https://www.root.cz/clanky/datove-typy-option-result-a-array-v-programovacim-jazyku-f/
  12. Datové typy Option, Result a Array v programovacím jazyku OCaml
    https://www.root.cz/clanky/datove-typy-option-result-a-array-v-programovacim-jazyku-ocaml/
  13. Operátory v programovacím jazyku OCaml
    https://www.root.cz/clanky/operatory-v-programovacim-jazyku-ocaml/
  14. Operátory v programovacím jazyku F#
    https://www.root.cz/clanky/operatory-v-programovacim-jazyku-f/
  15. Definice uživatelských datových typů v jazyku F#
    https://www.root.cz/clanky/definice-uzivatelskych-datovych-typu-v-jazyku-f/
  16. Definice uživatelských datových typů v jazyku OCaml
    https://www.root.cz/clanky/definice-uzivatelskych-datovych-typu-v-jazyku-ocaml/
  17. Rekurzivní datové typy v jazyku OCaml
    https://www.root.cz/clanky/rekurzivni-datove-typy-v-jazyku-ocaml/
  18. Řídicí konstrukce v programovacím jazyku OCaml
    https://www.root.cz/clanky/ridici-konstrukce-v-programovacim-jazyku-ocaml/
  19. LunarML: až překvapivě kvalitní transpiler z jazyka Standard ML do jazyků Lua a JavaScript
    https://www.root.cz/clanky/lunarml-az-prekvapive-kvalitni-transpiler-z-jazyka-standard-ml-do-jazyku-lua-a-javascript/
  20. LunarML: definice a volání různých variant funkcí
    https://www.root.cz/clanky/lunarml-definice-a-volani-ruznych-variant-funkci/
  21. LunarML: definice vlastních operátorů a pokročilý typový systém jazyka
    https://www.root.cz/clanky/lunarml-definice-vlastnich-operatoru-a-pokrocily-typovy-system/

Odkazy na Internetu

  1. Elm in 2026: The Language That Stopped Changing — And What That Actually Means
    https://medium.com/@reactjsbd/elm-in-2026-the-language-that-stopped-changing-and-what-that-actually-means-2b08c598528a
  2. The Syntax Cliff: Teaching syntax with Elm 0.19.1
    https://elm-lang.org/news/the-syntax-cliff
  3. Stránky projektu Elm
    https://elm-lang.org/
  4. Binární balíčky s jazykem Elm
    https://github.com/elm/com­piler/releases
  5. Pískoviště pro jazyk Elm
    https://elm-lang.org/try
  6. LunarML documentation
    https://lunarml.readthedoc­s.io/en/latest/index.html
  7. Standard ML of New Jersey
    https://www.smlnj.org/
  8. Programming Languages: Standard ML – 1 (a navazující videa)
    https://www.youtube.com/wat­ch?v=2sqjUWGGzTo
  9. 6 Excellent Free Books to Learn Standard ML
    https://www.linuxlinks.com/excellent-free-books-learn-standard-ml/
  10. SOSML: The Online Interpreter for Standard ML
    https://sosml.org/
  11. ML (Computer program language)
    https://www.barnesandnoble­.com/b/books/other-programming-languages/ml-computer-program-language/_/N-29Z8q8Zvy7
  12. Strong Typing
    https://perl.plover.com/y­ak/typing/notes.html
  13. What to know before debating type systems
    http://blogs.perl.org/user­s/ovid/2010/08/what-to-know-before-debating-type-systems.html
  14. Types, and Why You Should Care (Youtube)
    https://www.youtube.com/wat­ch?v=0arFPIQatCU
  15. DynamicTyping (Martin Fowler)
    https://www.martinfowler.com/bli­ki/DynamicTyping.html
  16. DomainSpecificLanguage (Martin Fowler)
    https://www.martinfowler.com/bli­ki/DomainSpecificLanguage­.html
  17. Language Workbenches: The Killer-App for Domain Specific Languages?
    https://www.martinfowler.com/ar­ticles/languageWorkbench.html
  18. Effective ML (Youtube)
    https://www.youtube.com/watch?v=-J8YyfrSwTk
  19. Why OCaml (Youtube)
    https://www.youtube.com/wat­ch?v=v1CmGbOGb2I
  20. CSE 341: Functions and patterns
    https://courses.cs.washin­gton.edu/courses/cse341/04wi/lec­tures/03-ml-functions.html
  21. Comparing Objective Caml and Standard ML
    http://adam.chlipala.net/mlcomp/
  22. 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
  23. Cheat Sheets (pro OCaml)
    https://www.ocaml.org/doc­s/cheat_sheets.html
  24. Syllabus (FAS CS51)
    https://cs51.io/college/syllabus/
  25. Abstraction and Design In Computation
    http://book.cs51.io/
  26. Learn X in Y minutes Where X=Standard ML
    https://learnxinyminutes.com/doc­s/standard-ml/
  27. CSE307 Online – Summer 2018: Principles of Programing Languages course
    https://www3.cs.stonybrook­.edu/~pfodor/courses/summer/cse307­.html
  28. CSE307 Principles of Programming Languages course: SML part 1
    https://www.youtube.com/wat­ch?v=p1n0_PsM6hw
  29. CSE 307 – Principles of Programming Languages – SML
    https://www3.cs.stonybrook­.edu/~pfodor/courses/summer/CSE307/L01_SML­.pdf
  30. SML, Some Basic Examples
    https://cs.fit.edu/~ryan/sml/in­tro.html
  31. History of programming languages
    https://devskiller.com/history-of-programming-languages/
  32. History of programming languages (Wikipedia)
    https://en.wikipedia.org/wi­ki/History_of_programming_lan­guages
  33. 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/
  34. The Evolution Of Programming Languages
    https://www.i-programmer.info/news/98-languages/8809-the-evolution-of-programming-languages.html
  35. Evoluce programovacích jazyků
    https://ccrma.stanford.edu/cou­rses/250a-fall-2005/docs/ComputerLanguagesChart.png
  36. Poly/ML Homepage
    https://polyml.org/
  37. PolyConf 16: A brief history of F# / Rachel Reese
    https://www.youtube.com/wat­ch?v=cbDjpi727aY
  38. Programovací jazyk Clojure 18: základní techniky optimalizace aplikací
    https://www.root.cz/clanky/pro­gramovaci-jazyk-clojure-18-zakladni-techniky-optimalizace-aplikaci/
  39. Moscow ML Language Overview
    https://itu.dk/people/ses­toft/mosml/mosmlref.pdf
  40. ForLoops
    http://mlton.org/ForLoops
  41. Funkcionální dobrodružství v JavaScriptu
    https://blog.kolman.cz/2015/12/fun­kcionalni-dobrodruzstvi-v-javascriptu.html
  42. Recenze knihy Functional Thinking (Paradigm over syntax)
    https://www.root.cz/clanky/recenze-knihy-functional-thinking-paradigm-over-syntax/
  43. Currying
    https://sw-samuraj.cz/2011/02/currying/
  44. Používání funkcí v F#
    https://docs.microsoft.com/cs-cz/dotnet/fsharp/tutorials/using-functions
  45. Funkce vyššího řádu
    http://naucte-se.haskell.cz/funkce-vyssiho-radu
  46. Currying (Wikipedia)
    https://en.wikipedia.org/wi­ki/Currying
  47. Currying (Haskell wiki)
    https://wiki.haskell.org/Currying
  48. Haskell Curry
    https://en.wikipedia.org/wi­ki/Haskell_Curry
  49. Moses Schönfinkel
    https://en.wikipedia.org/wi­ki/Moses_Sch%C3%B6nfinkel
  50. Fibonacci sequence
    https://en.wikipedia.org/wi­ki/Fibonacci_sequence
  51. Moonscript: jazyk inspirovaný CoffeeScriptem určený pro ekosystém jazyka Lua
    https://www.root.cz/clanky/moonscript-jazyk-inspirovany-coffeescriptem-urceny-pro-ekosystem-jazyka-lua/
  52. Moonscript: jazyk inspirovaný CoffeeScriptem určený pro ekosystém jazyka Lua (2)
    https://www.root.cz/clanky/moonscript-jazyk-inspirovany-coffeescriptem-urceny-pro-ekosystem-jazyka-lua-2/
  53. Moonscript: jazyk inspirovaný CoffeeScriptem určený pro ekosystém jazyka Lua (dokončení)
    https://www.root.cz/clanky/moonscript-jazyk-inspirovany-coffeescriptem-urceny-pro-ekosystem-jazyka-lua-dokonceni/
  54. Programovací jazyk Lua v roli skriptovacího jazyka pro WWW stránky
    https://www.root.cz/clanky/pro­gramovaci-jazyk-lua-v-roli-skriptovaciho-jazyka-pro-www-stranky/
  55. Transcrypt: technologie umožňující použití Pythonu v prohlížeči
    https://www.root.cz/clanky/transcrypt-technologie-umoznujici-pouziti-pythonu-v-prohlizeci/
  56. GopherJS: transpřekladač z jazyka Go do JavaScriptu
    https://www.root.cz/clanky/gopherjs-transprekladac-z-jazyka-go-do-javascriptu/
  57. Rychlost CPythonu 3.11 a 3.12 v porovnání s JIT a AOT překladači
    https://www.root.cz/clanky/rychlost-cpythonu-3–11-a-3–12-v-porovnani-s-jit-a-aot-prekladaci-pythonu/
  58. Seriál F# a OCaml
    https://www.root.cz/serialy/f-a-ocaml/
  59. Haskell or Standard ML for beginners?
    https://stackoverflow.com/qu­estions/810409/haskell-or-standard-ml-for-beginners#813646
  60. Awesome transpilers
    https://github.com/milahu/awesome-transpilers
  61. Languages that compile to JS (from CoffeeScript wiki)
    https://gist.github.com/mat­thiasak/c3c9c40d0f98ca91def1
  62. Common Language Runtime
    https://en.wikipedia.org/wi­ki/Common_Language_Runtime
  63. 7 Old Programming Languages Developers Still Won’t Quit
    https://medium.com/javarevisited/7-old-programming-languages-developers-still-wont-quit-42f8136ef678
  64. Lambdera: A delightful platform for full-stack web apps
    https://www.lamdera.com/
  65. Mario Rogic – Elm as a Service
    https://www.youtube.com/wat­ch?v=nSrucNcwlA8
  66. Developer Happiness on the Front End with Elm
    https://www.youtube.com/wat­ch?v=kuOCx0QeQ5c
  67. Elm & The Future of Open Source (with Evan Czaplicki)
    https://www.youtube.com/wat­ch?v=0SUM4869ODc
  68. Package Managers Need to Cool Down
    https://nesbitt.io/2026/03/04/package-managers-need-to-cool-down.html
  69. Fable
    https://fable.io/
  70. „Making Impossible States Impossible“ by Richard Feldman
    https://www.youtube.com/wat­ch?v=IcgmSRJHu8
  71. Error Messages: The Art of Effective Communication in Software Development
    https://dev.to/favourmark05/writing-proper-error-messages-the-art-of-effective-communication-in-software-development-emj

Autor článku

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