# Mònada (programació funcional)

En programació funcional una mònada és un TAD sense tipus concrets, corresponent a una estructura algebraica d'un sol element (d'aquí el nom de mònada), on la finalitat de les operacions és modelar la composició i la seqüencialitat de les computacions (accions amb efectes) mitjançant l'encadenament, separant la composició temporal, de l'execució, així com incorporar el resultat de cada operació sobre l'entorn.
La mònada modela una computació i pot ser vista com una acció amb efecte (un canvi), que produeix un resultat.
Les mònades es poden compondre, mitjançant l'encadenament, amb operacions sobre el resultat de la precedent (que poden incloure efectes col·laterals), estalviant, respecte de la programació imperativa, les variables locals emprades per aquesta per desar resultats.
* (return v) representa una computació elemental que ofereix v com a resultat. return és el generador de la mònada.
* (>>=), anomenada bind, és la composició de computacions, encadenant una acció amb la següent en forma de funció sobre el resultat de la precedent.
En notació Haskell:
La mònada (signatura) s'implementa per a un tipus (estructura) que pot ser vist com un contenidor d'un sol element que pot ser el resultat, però no sempre és el resultat tot sol. #La mònada Writer aparella com a valor el resultat i un element combinable (un Monoide). #La mònada Reader conté com a valor una funció de tipus (entorn -> resultat). #La mònada State conté com a valor una altra tipus de funció (estat -> (resultat, nouEstat)).
Té aplicació en llenguatges de programació no-estrictes, on l'ordre de les operacions és indeterminat, principalment al Haskell i també en altres àmbits, en entorns on l'ordre de les operacions no està garantit, com ara encadenament de transaccions en memòria (mònada STM a Haskell i a OCaml), encadenament d'operacions asíncrones (mònada Par a Haskell, Asynchronous Workflows a F#), etc.
Això facilita als lleng. funcionals complementar la part funcional pura, amb efectes com ara operacions d'entrada/sortida, ops. sobre l'entorn exterior, canvis d'estat, i també el preprocés i optimització de les operacions abans de la seva execució.

## Les lleis de la mònada.

| return x >>= f | ≡ | f x | -- identitat per l'esquerra |
| m >>= return | ≡ | m | -- identitat per la dreta |
| m >>= (\x -> f x >>= g) | ≡ | (m >>= f) >>= g | -- associativitat |
La funció `fail` s'utilitza en la sintaxi específica de blocs d'encadenaments monàdics, els blocs do, per disparar una excepció en cas que falli l'encaix del patró del paràmetre de la funció d'efectes, però serà expulsada de la classe Mònada a GHC 8.8, cap a una classe específica MonadFail de Control.Monad.Fail. L'ús de patrons en l'encadenament requerirà que la mònada implementi MonadFail evitant les petades per l'ús de patrons en mònades que no els suporten. Fase final de la proposta implementada a GHC 8.8.
En Haskell podem expressar (>>=), en termes de fmap i join, doncs la classe Monad actualment deriva de la classe Applicative que deriva al seu torn de Functor. El nom "flatMap" que (>>=) pren en altres llenguatges (Scala, Java8) ve de l'ús d'aquests conceptes:

## Mònades segons la quantificació de resultats

Seqüenciació d'accions amb
* resultat únic:
** IO: entrada/sortida, excepcions I/O i canvis d'estat de variables globals IORef.
** ST: encapsulament de canvis d'estat en un àmbit local (variables STRef).
* resultat opcional (de funcions o bé d'accions que poden fallar):
** la mònada Maybe: èxit o fallada de funcions definides parcialment.
** la mònada (Either tipusError): èxit o fallada de la validació amb try d'accions que poden llançar excepcions.
* resultat múltiple: la mònada llista (mecanisme de les llistes per comprensió).

## Mònades i estrictesa

Les mònades no impliquen estrictesa (avaluació del primer argument de (>>=) malgrat que el segon no en demani el resultat com a paràmetre: cas del comodí '_') sinó que depèn de la implementació. La mònada IO és d'avaluació estricta, la mònada llista [a] no, i per exemple la mònada State té versions estricta i d'avaluació tardana (lazy)

## Mònades amb efecte fallada

Afegint la llei de l'element absorbent per l'esquerra
mzero >>= f ≡ mzero
L'element absorbent per l'esquerra fa inútil l'avaluació de les computacions subseqüents, ja que el resultat és el mateix valor, i pot indicar una situació d'error que invalidi la continuació de les computacions.
L'encadenament de computacions amb mònades que compleixin la regla de l'element absorbent en (>>=) per algun valor del tipus, evita haver de comprovar resultats d'error a cada pas nou en la seqüència.

### La mònada Maybe (computacions que poden fallar)

Nothing n'és l'element absorbent per l'esquerra. Optimitza la seqüència evitant l'execució de computacions subseqüents a la que falla.
Exemple:

### La mònada Either (resultats duals)

Amplia el valor Nothing de la mònada Maybe amb un segon conjunt de valors, emprat sovint per designar els errors en computacions que poden fallar disparant excepcions.
Els constructors Left i Right, a més de l'accepció d'Esquerre i Dreta, també tenen el significat de Tort i Dret, explicitant així la correcció del resultat.
Tots els elements amb constructor Left (Left l) són elements absorbents per l'esquerra.
Exemple:

## Composició monàdica

Composició de Kleisli.

## La mònada IO

Haskell modela l'entrada/sortida com una seqüència encadenada d'operacions (per forçar-ne la serialització degut a l'avaluació no-estricta), encapsulant els canvis d'estat d'accés a fitxers. Aquest model encaixa amb el concepte de mònada, donant lloc a la mònada IO.
La funció inicial main de qualsevol programa en Haskell ha de ser una expressió d'operacions d'ent./sortida i, per tant, del tipus de la mònada IO.
Vegeu el tipus de (failIO s)

## Blocs do: notació especial de les expressions monàdiques

La clàusula do exposa l'encadenament de manera seqüencial, amb una expressió monàdica per línia, introduint l'estil imperatiu.
el bloc do és un artifici sintàctic que es tradueix a una única expressió, relligant les línies amb operacions de mònada com el que segueix:
* les del tipus x <- expr_monàdica es concatenen amb les següents per encadenament (>>=) amb funció anònima de param. x i la continuació com a cos.
* les altres es concatenen amb encadenament (>>) sense passar resultats

### Clàusula let dins el bloc do

let a nivell de do (NO és el mateix que let..in) permet establir definicions basant-se en resultats d'efectes precedents, cosa que no és possible amb clàusules where.

#### "let" var1 "=" expr1 {";" var2 "=" expr2}

    obté el valor de les expressions. let introdueix un subbloc, que es podrà delimitar o bé pel sagnat, o bé amb claus i separadors ';', i quines variables definides queden visibles a la resta del bloc do.

## Control imperatiu

Operacions comparables al control dels llenguatges imperatius.
El mòdul Control.Monad de Haskell aporta entre d'altres les següents funcions:

### if-then-else dins la clàusula do

-- segons el Haskell 98
-- segons el Haskell 2010 varia la sintaxi com a
acceptant el següent format:

### Subblocs do

Per posar més d'una instrucció en una branca d'un if o d'un case cal fer-ho en un subbloc do.

## Recursivitat en els blocs do

Parlem de Recursivitat mútua en definicions i accions amb efectes.

### Als subblocs let de definicions amb encaix

Els blocs let permeten, per l'avaluació tardana, la recursivitat mútua de les variables definides.
(anglès) >> In Haskell let is really let_rec
dona:

### Als subblocs rec d'efectes amb recursivitat mútua

A GHC, permeten recursivitat mútua a les accions (efectes col·laterals). Cal esmentar la pragma {-# LANGUAGE RecursiveDo #-} Vegeu ref.

## Seqüències de computacions sense lligar resultats - Functors aplicatius

De vegades interessa només obtenir la llista de resultats d'una seqüència de computacions amb efectes col·laterals però sense encadenar resultats.
L'operació sequence esmentada prèviament fa aquesta funció.
Aquest patró correspon a un combinador de la biblioteca Control.Monad que es diu ap (de aplicatiu)
Elevant una funció a efecte, la podrem utilitzar com a combinador:
Una funció de n paràmetres ens permet combinar els resultats de n efectes
Llavors la funció sequence es pot escriure
Generalitzant la manera de combinar una seqüència de computacions, en una mònada, sense encadenar resultats:
Això dona lloc a l'abstracció Applicative més simple que la Mònada però que està en els fonaments dels llenguatges funcionals.

### La classe Applicative

Expressa la combinació de computacions (amb efectes col·laterals) sense l'encadenament del resultat que permet la mònada. Signatura.
La classe Functor:
Per aplicar una funció de n arguments als resultats de n computacions en seqüència definides Applicative tenim les funcions liftAn:
A la mònada tenim les següents equivalències
però GHC defineix la instanciació a partir d'un tipus derivat (amb newtype) de nom WrappedMonad. per establir la relació entre els tipus.
Un exemple d'ús el trobem en els formularis web en haskell anomenats Formlets.
Aquí una versió de collita pròpia, com a producte de parells (entrada, resultat) per mostrar entrades i errors a validar per l'usuari:

### La classe Alternative (computacions alternatives)

Defineix un monoide sobre els functors aplicatius.
La interpretació de l'op. binària (<|>) no és sempre la intuïtiva. Està previst que Applicative esdevingui superclasse de Monad a GHC 7.10. De cara a una eliminació de duplicitats entre Mònada i Applicative es pretén que la relació d'Alternative amb Applicative sigui similar a la de MonadPlus amb Monad i que la implementació dels monoides d'Alternative i de MonadPlus donin el mateix resultat per als tipus que implementin ambdues classes. És el cas de les llistes.
* De la proposta Functor-Applicative-Monad:

## La classe MonadPlus (computacions amb solucions múltiples)

Defineix un Monoide sobre les computacions mònada. Permet expressar computacions amb solucions múltiples (zero o més) i l'opció de fallada (no avaluació de les computacions posteriors) i obtenir-ne la combinació de solucions.

### exemple: la mònada Llista

Exemple d'ús:
dona

### Llista per comprensió monàdica

Generalitzen la notació de Llistes per comprensió. L'ús de filtres requereix que la mònada implementi la classe MonadPlus
Vegeu ref.

### Ús de la construcció llista per comprensió amb qualsevol instància de MonadPlus

L'extensió MonadComprehensions permet emprar qualsevol mònada que sigui instància de MonadPlus, en la construcció llista per comprensió. Cal GHC >= 7.2.1
En el següent cas ja no és una llista per comprensió sinó una Maybe per comprensió
dona

## Transformadors de mònades

Aplicació sobre el tipus d'una mònada que en combina l'operativa (permet l'ús dels mètodes de diverses mònades en una), encapsulant una mònada dins la mònada transformada resultant. Vegeu
Implementen la classe MonadTrans
Les transformacions són apilables: se'n poden aplicar diverses. Si t i t' són transformadors de mònades, llavors el tipus (t' t m a) constitueix la mònada (t' t m) transformada de la (t m)
La classe MonadIO és per definir una versió optimitzada de lift de MonadTrans per elevar el tipus dels efectes des de la mònada IO quan hi ha transformacions interposades.

### Implementació del transformador MaybeT

El transformador MaybeT permetrà ampliar una mònada qualsevol amb la característica afegida de la mònada Maybe, d'evitar l'execució dels efectes posteriors a una fallada (op. fail).

#### La classe MonadTrans

La classe MonadTrans aporta lift que eleva un efecte des d'una mònada m a la mònada transformada (t m). Continuant el codi anterior:

### Exemple d'ús

Farem servir el transformador MaybeT que combina les computacions que poden fallar (vegeu més amunt) sobre la mònada IO resultant la mònada (MaybeT IO)
Caldrà elevar el tipus de les operacions sobre la mònada IO al de la mònada (MaybeT IO) amb lift.
runMaybeT permet "rebaixar" (contrari de lift: elevar) el tipus d'un efecte, de la mònada transformada (MaybeT m) al tipus de la mònada subjacent:

## Excepcions en una mònada - La classe MonadError

És un mecanisme de simulació d'excepcions només amb el tractament monàdic.
Implementa l'estratègia de combinar computacions que poden llançar excepcions saltant-se les computacions encadenades que segueixen la que llança l'error, fins a la sortida del gestor d'excepcions on recupera l'encadenament habitual.

### Exemple: la mònada (Either tipusExcepció)

El tipus (Either tipusExcepció tipusResultat) millora la info. del tipus Maybe afegint-hi informació de l'error. El constructor Right introdueix el resultat Correcte i el constructor Left l'Error. Igual que amb el tipus Maybe, el podem fer servir de tipus de computació com a mònada ((Either tipusExcepció) tipusResultat).

## Més mònades rellevants en Haskell
### La mònada Writer

Facilita la generació de traces i enregistraments (ang:logs) sense barrejar-los amb els resultats.
El domini de la mònada és un parell amb el resultat i l'enregistrament. Aquest darrer ha d'implementar un Monoide.

#### pass

    passa una funció per aplicar sobre l'enregistrament, aparellant-la amb el resultat

#### listen

    obté el parell (resultat, enregistrament)

#### tell

    estableix l'enregistrament al valor especificat

#### censor

    aporta la funció per aplicar a l'enregistrament i l'aplica amb pass

#### listens

    obté el parell retornat per listen i el retorna aplicant un selector a l'enregistrament
* Exemple d'ús amb el transformador WriterT.
dona el resultat
* Exemple d'ús sense transformador. la biblioteca de GHC a Control.Monad.Writer no inclou el tipus, i cal definir-lo, instanciant les classes requerides:
dona el resultat

### La mònada State

Facilita l'enfilada d'un estat a través de computacions que el modifiquen, encapsulant-ne els canvis en codi funcional pur.
Els valors de la mònada State són funcions de transició entre estats del tipus (estat -> (resultat, nouEstat)). Per avaluar-lo caldrà aplicar-lo sobre un estat inicial, obtenint un parell amb el resultat en primera posició: (runState computacióMonadState) estatInicial

### La mònada Reader

Facilita l'arrossegament d'un entorn d'associacions variable, per exemple la substitució de textos definits en plantilles, que poden augmentar o ésser tapades per noves definicions.
El valor de la mònada Reader és una funció sobre l'entorn: (entorn -> resultat). Per avaluar-lo caldrà aplicar-lo sobre un entorn inicial: (runReader computacióMonadReader) entornInicial

#### ask

    obté l'entorn

#### local

    avalua un efecte havent modificat l'entorn amb una funció (env -> env)

#### asks

    obté el resultat d'aplicar un selector (env -> a) sobre l'entorn.
Vegeu l'exemple.

### La mònada STM

STM (Software Transactional Memory) permet l'actualització consistent de variables en diferents fils d'execució mitjançant transaccions en memòria que admeten tot o res d'una seqüència de lectures i modificacions de les variables transaccionals.
Vegeu Haskell concurrent - STM.

### La mònada Par

Encadenament de càlculs simultanis

### El Functor aplicatiu Concurrently

A la biblioteca async, facilita l'execució simultània d'operacions I/O no blocants on el tipus Concurrently implementa un functor aplicatiu que permet combinar els resultats d'accions engegades asíncronament, esperant-ne la finalització conjunta, i també implementa Alternative per obtenir el resultat de la primera que acaba, anul·lant els fils d'execució de la resta d'operacions engegades.

## Mònades a l'OCaml

* la biblioteca LWT (light-weight cooperative threads) modela la seqüenciació de computacions d'entrada/sortida no-blocants (asíncrones) en una mònada.
* la biblioteca coThreads proporciona la mònada STM a OCaml
* Guia sobre Mònades per a OCaml Arxivat 2012-02-27 a Wayback Machine. (anglès)
* Extensió sintàctica per a les mònades a OCaml.

## Mònades a l'F#

Vegeu Computation expressions i també Async. Workflows
* Extensió sintàctica per a les Mònades a F#.

## Mònades a Scala

La clàusula for corresponent a les llistes per comprensió respon a un encadenament monàdic.
Si en comptes de llistes hi subministrem dades de tipus Option[A] el resultat és també del tipus de la mònada Option (equivalent de la Maybe en Haskell).
Vegeu presentació "Introduction to Monads in Scala".

## Relacionat

* Functor aplicatiu
* Fletxa (programació funcional)

## Referències

* 1 2 Haskellwiki - La mònada(anglès)
* ↑ Haskell wiki - Monad laws(anglès)
* ↑ La classe MonadFail
* ↑ La proposta MonadFail Arxivat 2019-06-02 a Wayback Machine.(anglès)
* ↑ GHC 8.8.1 Notes de la versió(anglès) La fase final de la proposta MonadFail (exclusió de `fail`) hi ve implementada.
* 1 2 «Biblioteca OCaml Light weight threads per a computacions IO no blocants (asíncrones)». Arxivat de l'original el 2012-06-11. [Consulta: 14 febrer 2013].
* ↑ FilterMonadic Arxivat 2017-06-25 a Wayback Machine.(anglès)
* ↑ La classe d'objectes Optional<T>(anglès)
* 1 2 Monads are not about strictness(anglès)
* ↑ Control.Monad.ST.Strict(anglès)
* ↑ Control.Monad.ST.Lazy(anglès)
* ↑ «Codi font de la mònada Maybe». Arxivat de l'original el 2011-10-02. [Consulta: 6 setembre 2011].
* ↑ Composició de Kleisli
* ↑ mòdul GHC.IO funció failIO
* ↑ Notació especial "do" a la mònada (anglès)
* ↑ El mòdul Control.Monad
* ↑ Haskell98 - Condicionals Traducció de if-then-else(anglès)
* ↑ Do i l'if-then-else Arxivat 2010-07-02 a Wayback Machine.(anglès)
* ↑ Haskell2010 (anglès) DoAndIfThenElse hi és comprès.
* 1 2 Bloc Do recursiu Arxivat 2005-11-29 a Wayback Machine.(anglès)
* ↑ Do recursiu i MonadFix(anglès)
* ↑ L'abstracció Applicative - Programació aplicativa amb efectes col·laterals(anglès)
* 1 2 Applicative i Alternative Arxivat 2013-12-03 a Wayback Machine.(anglès)
* ↑ La classe Functor Arxivat 2013-06-09 a Wayback Machine.(anglès)
* ↑ WrappedMonad(anglès)
* ↑ Formlets - functors aplicatius als formularis
* ↑ Notes de la versió 7.8.1(anglès)
* 1 2 Functor-Applicative-Monad Proposal(anglès)
* ↑ Why is Alternative concatenating lists instead of choosing the first non-empty one?
* ↑ HaskellWiki - La classe MonadPlus(anglès)
* ↑ Extensions GHC - Llista per comprensió monàdica Arxivat 2011-09-27 a Wayback Machine.(anglès)
* ↑ GHC - Notes de la versió 7.2.1(anglès)
* ↑ Viquillibre Haskell - Monad Transformers (anglès)
* ↑ la classe MonadTrans(anglès)
* ↑ la classe MonadIO Arxivat 2011-08-09 a Wayback Machine. (anglès)
* ↑ La classe MonadError(anglès)
* ↑ La mònada Writer(anglès)
* ↑ La mònada State(anglès)
* ↑ Diferències entre State i ST
* ↑ mòdul Control.Monad.State.Lazy
* 1 2 La mònada Reader(anglès)
* ↑ Biblioteca Async (anglès)
* ↑ coThreads (anglès) Mònada STM per a OCaml (anglès)
* ↑ Syntax extension for Monads in Ocaml(anglès)
* ↑ Viquillibre anglès de F# - Computation expressions(anglès)
* 1 2 Microsoft - F# Computation expressions(anglès)
* ↑ Asynchronous Workflows
* ↑ F# survival guide (anglès) Vegeu Chapter 16 Workflows, Asynchronous & Parallel Programming
* ↑ viquillibre - Computation_Expressions#Syntax_Sugar
* ↑ Monads in Scala(anglès)
* ↑ Introduction to Monads in Scala(anglès)

## Enllaços externs

* Haskell.org - Tot sobre les mònades (anglès)
* Mònades al viquillibre anglès sobre Haskell (anglès)
* Difference between State, ST, IORef, and MVar Diferències entre les mònades State i ST, i les referències (punters) IORef i MVar