# Monade

## Računski učinki

Primeri:

1. Vhod/izhod (I/O): stdio, stdout, datoteke
2. Izjema
3. Stanje (RAM, spremenljivka, stanje avtomata)
4. Nedeterminizem: možnih je več rezultatov

    ```
        f(e₁, e₂) -- vrstni red računanja e₁ in e₂
    ```

5. Verjetnostno računanje: rezultati so porazdeljeni verjetnostno.
6. Timeout: program prekine delovanje, če se izvaja predolgo.
7. Non-termination: koda se ne ustavi


## Monada

### Osnovna struktura

Ločimo med **čistimi** vrednostmi (podatki, ki so že izračunani,
jih ne izvjajamo in nimajo učinkov) in **izračuni** (izjavamo,
lahko se pojavijo učinki).

1. `return`: Čiste vrednosti so izračuni: vsako vrednost lahko predstavimo kot izračun, katerega rezultat je ta vrednost.
2. `bind`, `>>=`: izračune lahko kombiniramo, sestavljamo.

Če imamo funkciji `f : A → B` in `g : B → C` ju lahko kombiniramo
`g ∘ f : A → C`.

Imamo izračuna `c₁` in `c₂`:

* `c₁` vrne vrednost `v` (in povzroča učinke)
* `c₂` vrnjeno vrednost sprejme in se izvede ter vrne vrednost `w` 

Primer:

* `c₁` je izračun: `print "Hello, " ; return 5`
* `c₂` sprejme rezultat od `c₁`, recimo `x`, izpiše `"world!"` ter vrne `x+1`

Ko ju kombiniramo `c1 >>= c2`:
* izračun: na zaslon se izpiše `"Hello, world!"` in vrne se rezultat `6`

### Haskell

Učinke simuliramo tako, da sprogramiramo monade.

1. Izračune modeliramo z nekim konstruktorjem tipov.
   Ideja: izračune, ki vračajo vrednosti tipa `a`, predstavimo
          z nekim tipom `m a`
2. Definiramo `return`
3. Definiramo `>>=`

