Legile monadei

From HaskellWiki

Toate instantele clasei Monad trebuie sa se conformeze axiomelor de mai jos:(dati click pe Monad pentru explicatii in engleza despre clasa Monad)

1. return a >>= f  =  f a
2. m >>= return  =  m
3. (m >>= f) >>= g = m >>= (\x -> f x >>= g)

Ce semnifica aceste reguli pentru programatorul interesat de aspectele practice ?[edit]

Daca scriem aceste reguli in do-notatie obtinem egalitatile:

1. do { x' <- return x            do { f x
      ; f x'               ==        }
      }

2. do { x <- m             ==     do { m
      ; return x }                   }

3. do { y <- do { x <- m          do { x <- m
                ; f x                ; do { y <- f x
                }          ==             ; g y
      ; g y                               }
      }                              }

                                  do { x <- m
         care conform  3.14  (?)     ; y <- f x
                           ==        ; g y
                                     }

Cu aceasta notatie semnificatia regulilor este clara.

Dar de ce trebuie monadele sa urmeze aceste reguli ?[edit]

Atunci cand scriem un program in forma din stanga ne asteptam ca el sa faca exact acelasi lucru ca si forma sa din dreapta. Iar in practica, tot modificand un program se poate ajunge la forme ca cea din stanga care vor trebui sa se comporte asa cum ne asteptam.

Primul exemplu: incepatorii au tendinta sa scrie:

skip_and_get = do { unused <- getLine
                  ; line <- getLine
                  ; return line
                  }

iar un asemenea cod i-ar innebuni si pe incepatori si pe veterani daca nu s-ar comporta (conform legii nr. 2) ca

skip_and_get = do { unused <- getLine
                  ; getLine
                  }

Acesta ar fi doar un motiv necesar ca monadele sa verifice legea/axioma nr. 2.

Al doilea exemplu: Sa continuam cu folosirea lui skip_and_get:

main = do { answer <- skip_and_get
          ; putStrLn answer
          }

Cel mai usor mod de a ne imagina exact efectul acestui apel este sa il scriem prin substitutie. Skip_and_get se inlocuieste cu codul lui. (daca un compilator sau interpretor procedeaza exact asa este o cu totul alta discutie):

main = do { answer <- do { unused <- getLine
                         ; getLine
                         }
          ; putStrLn answer
          }

si numai aplicand axioma/legea, nr.3, putem pretinde ca este echivalent cu:

main = do { unused <- getLine
          ; answer <- getLine
          ; putStrLn answer
          }

Legea/axioma nr. 3 este in ciuda aparentelor uluitor de penetranta: cu siguranta ati presupus-o adevarata si ati folosit-o dar niciodata nu v-ati pus problema existentei sale in forma axiomatica de mai sus.

Indiferent daca compilatorul foloseste sau nu (pentru optimizari) aceste legi cu siguranta veti dori sa fiti sub "protectia lor" pentru binele (adica bunul comportament al) programelor dumneavoastra. Doar in acest mod puteti sa va feriti de a va smulge parul din cap din cauza unor comportamente anti-intuitive. Acestea s-ar manifesta dupa niste modificari altminteri minore cum ar fi introducerea unor "return"-uri redundante sau schimbarea numarului de do-uri imbricate.

Explicatii conexe in limba engleza gasiti la Category:Standard_classes si Category:Monad la inceputul acestei pagini.


Pagina indexata la indexul Categories:Ro


<= Inapoi la pagina principala Ro/Haskell.

<- Inapoi la Intrebarile incepatorului Ro/Haskell.