import Monad
import Control.Monad.ST
import Data.STRef

-- monada ST s a -- vypocet hodnoty typu a, pracujici s vnitrnim stavem indexovanym typovou promennou s
-- stav obsahuje napriklad pole (viz minuly priklad), reference:

reference::ST s (Int,Int)
reference =
  do
   a <- newSTRef 5
   b <- newSTRef 8
   zvys a
   swap a b
   va <- readSTRef a
   vb <- readSTRef b
   return (va,vb)

zvys::STRef s Int -> ST s ()
zvys ref = modifySTRef ref (+1)

swap::STRef s a->STRef s a->ST s ()
swap x y =
  do
    vx <- readSTRef x
    vy <- readSTRef y
    writeSTRef x vy
    writeSTRef y vx

-- runST::(forall s. ST s a) -> a
-- runST reference = (8,6)

-- k cemu je typova promenna s?
-- utek = runST (newSTRef 42) nejde otypovat
-- (typova promenna s je kvantifikovana, a nemuze "utect" do
-- typu vysledku

-- Dusledek:  nejde napsat vyraz typu
-- let ref = runST (newSTRef True) in runST (readSTRef ref)
-- reference je vazana uvnitr jednoho stavu!

-- vstupy a vystupy:
-- type IO a = ST RealWorld a
-- fixovany typ RealWorld zajistuje, ze na objekty typu IO nelze
-- volat runST (jediny zpusob, jak takove akce spustit, je
-- prirazeni do main (a funkce unsafePerformIO -- nepouzivat!!!))
