Főmenü megnyitása

Módosítások

nincs szerkesztési összefoglaló
class MultiParam a b where
foo :: a -> b -> a
</source>
 
 
=== Monádok ===
 
Mint ahogyan arról már volt szó, a Haskell függvényei mellékhatás-mentesek. Ez azt jelenti, hogy a program környezete nem lehet hatással a programra, és fordítva. Körnzezet alatt értendő minden, ami nem szigorúan maga a program.
Ilyen környezetben persze nem lehetne tul hasznos programokat írni, hiszen egy valamire való program, folyamatos interakcióban van a környezetével. A másik probléma, hogy a lusta kiértékelés révén nem egyértelmű, hogy mi milyen sorrendben hasjtódik végre és ennek a sorrendnek a kikényszerítése ha nem is megoldhatatlan de problémás
 
Haskellben ezeket a problémákat úgy orvosoláták, hogy bevezették a kategória elméletből ismert monádokat. Ezek egyfelől a rajtuk végezhető operátorok segítéségével kikényszerítik a sorrendiséget, másfelől a haskell eszközeivel jól elkülönítik a mellékhatásos elemeket a mellékhatás-mentes elemektől.
 
==== Monádok használata ====
 
===== IO Monád =====
 
Nem minden Monád mellékhatásos. Mellékhatásosságot, csak az IO Monád enged meg.
A jól ismert hello world program is mellékhatásos, hiszen kiírja, hogy "hello world!"
 
<source lang=haskell>
main :: IO ()
main = putStrLn "Hello World!"
</source>
monádokra jellemzőbb szintaxissal (előbbi akkor használatos, ha a monad egyettlen utasításból áll)
<source lang=haskell>
main = do
putStrLn "Hello World!"
</source>
Ha több utasításunk van
<source lang=haskell>
main = do
putStrLn "name?"
name <- getLine
putStrLn ("Hello " ++ name ++ "!")
</source>
Fontos kiemelni, hogy ''name'' nem egy változó, csak egy cimke(pontosabban egy függvény paraméter (lásd: És ami mögötte van)).
''getLine'' típusa: ''IO String'' - Egy olyan IO Monad. mely egy String típusú számítást tárol. Ez a számítás minannyiszor végrehajtódik, ahányszor futtatjuk.
 
Más IO Monádokat is be lehet emelni
<source lang=haskell>
main = do
putStrLn "name?"
name <- getLine
printName name
 
printName :: IO ()
printName = do
putStrLn ("Hello " ++ name ++ "!")
</source>
 
 
==== És ami mögötte van ====
 
A Monádok legalapvetőbb operátora a ''bind''. Típusa
<source lang=haskell>
(>>=) :: m a -> (a -> m b) -> m b
</source>
ahol ''m'' a monád, ''a'' és ''b'' pedig monadikus számítások típusai.
 
Közelebbről:
Két paraméteres függvény, első paramétere egy ''a'' monád, második paramétere egy függvény, ami ''a'' típusról képez ''b'' monádra. (>>=) operátor végrehajtja ''a'' monádot, majd az eredményét applikálja a második paraméterül kapott függvényre.
 
A Monádokat Haskellben egy osztály definiálja
<source lang=haskell>
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
fail :: String -> m a
</source>
''(>>)'' operátor szimplán kiszámolja szekvenciálisan két paraméterét. Olyan esetben alkalmazzuk, mikor a második monádhoz nem szükséges az első értéke.
''return'' kvázi becsomagol egy értéket, egy monádba.
''fail'' olyan esetekben hajtódik végre, amikor a ''bind'' második paraméterére applikálskor minta illesztési hiba történik. Nem szokás használni ezt a függvényt, sokan tervezési hibának tartják ezt az elemet.
 
A Haskell egy kényelmes szintaxist kínál monádok alkalmazására, ami kell is, hiszen látható, hogy (>>=) operátor közvetlen alkalmazása nem a legkényelmesebb.
Ez a ''do'' szintaxis, ahogy az 'IO Monád' cimkénél látható.
 
<source lang=haskell>
main = do
putStrLn "name?"
name <- getLine
putStrLn ("Hello " ++ name ++ "!")
</source>
 
Átírása
 
<source lang=haskell>
main = (putStrLn "name?") >> (getLine >>= (\ name ->
(putStrLn ("Hello " ++ name ++ "!"))))
</source>
 
Névtelen felhasználó