# Característiques del llenguatge Haskell

Característiques del llenguatge de programació Haskell

## Fonamentat en el càlcul lambda

El càlcul lambda es basa (entre d'altres regles) en la reducció d'expressions, per l'aplicació sistemàtica d'una funció al primer paràmetre, obtenint una funció dels paràmetres que li manquen.
Això facilita l'ús d'aplicacions parcials (de menys paràmetres del que correspon a la seva aritat), en funcions d'ordre superior.

### separació de codi funcional pur i codi amb efectes col·laterals

L'assignació de tipus específics al codi impur (amb efectes sobre l'entorn: ent./sort., canvis d'estat, ...) facilita la distinció del codi pur (el que només depèn dels paràmetres) per a millores de rendiment mitjançant el paral·lelisme (procés en paral·lel).

#### codi pur (el resultat només depèn dels paràmetres)

   * L'ordre de les operacions és irrellevant.
   * l'ordre d'execució dels operadors en una expressió queda a discreció de l'optimitzador del compilador, per tant serà indeterminat.

#### codi impur (modifica o depèn de l'estat de l'entorn)

   * Una acció (com ara: getLine) produeix un resultat. Un bloc d'accions pot expressar-se de diverses maneres.
   * L'ordre és rellevant (el resultat de la seq. d'efectes coŀlaterals depèn de l'ordre d'execució)
   * El tipus de l'acció/efecte és el de l'entorn que l'acció modifica parametritzat pel tipus del resultat
Les accions es poden compondre
* per encadenament del resultat (serialització temporal)
* per combinació dels resultats (les accions poden ser simultànies)

### separació d'especificació i execució

El codi d'un mòdul no s'executa en l'ordre d'especificació, sinó mitjançant l'avaluació no-estricta, partint de l'expressió arrel main del mòdul Main que processa els arguments de la crida des de la consola de comandes.

#### avaluació no-estricta, normalment tardana - Thunks

En avaluació tardana les expressions, definides en variables i paràmetres, no es calculen quan es formulen sinó en el moment que se'n demana el valor en una altra expressió. Correspon a l'expressió anglesa lazy evaluation.
Haskell és d'avaluació no-estricta, que vol dir que l'avaluació va de l'arrel a les branques en l'arbre d'operacions de l'expressió. L'avaluació comença per l'expressió definida a la clàusula main. En en cas de (b * c + a) primer s'avalua el (+) i després el (*), al revés dels llenguatges estrictes. Les altres definicions s'avaluen sota comanda (avaluació tardana). D'aquesta manera només s'avaluen les subexpressions que facin falta, estalviant càlculs.
A la pràctica Haskell no és un llenguatge purament tardà. L'encaix de patrons és, normalment, estricte —almenys s'avalua si tindrà èxit—, i un analitzador d' estrictesa determina quan un terme serà sempre requerit en les expressions, i converteix la seva avaluació en primerenca (ang.: eager evaluation). El programador també pot forçar l'estrictesa com s'explica més avall.
Thunk és el nom de la càpsula de codi corresponent a cada expressió pendent d'avaluar.

### separació d'estructura i operacions (comparat amb la POO)

Haskell. a diferència dels lleng. amb orientació a objectes separa estructures de dades i comportament.
Els tipus de dades no impliquen operacions. Si són simples (ex.: Int, Double), defineixen el conjunt de valors, i si són compostos (tipus producte o tipus suma (unió discriminada de tipus)) defineixen l'estructura (clàusula data).
Les operacions sobre el tipus poden agrupar-se en "classes de tipus", equivalents en la orientació a objectes a les interfícies, i són com mòduls abstractes parametritzats pel tipus. Per fer-ne ús cal generar una instància de la classe genèrica per al tipus concret, aportant la implementació.
Per ser un llenguatge d'avaluació no-estricta, l'execució comença per l'avaluació de la clàusula d'engegada main, calculant les expressions que calguin quan se'n demana el valor (avaluació tardana) i no quan es defineix l'expressió (optimitzacions a banda).

### associació única de valors a identificadors

No es poden fer dues associacions al mateix identificador en el mateix àmbit (a nivell de mòdul, let o where)

### Composició de tipus

Els tipus (conjunts de valors) es poden compondre, partint dels tipus primitius i enumeracions, en tipus producte (etiquetats: els registres; anònims: les tuples) i tipus suma (cas de variants no-parametritzades: les enumeracions; variants parametritzades: unió discriminada), distingint-los amb un constructor que ens permetrà discriminar-los en l'encaix de patrons. Vegeu #tipus algebraics.
Les famílies de tipus permeten generalitzar els tipus basant-se en un o més índexs i concretar-ne instàncies de diferent estructura.

### Composició de comportament

Les classes designen la signatura (operacions) referides a variables de tipus i no a tipus concrets (com a les signatures del ML Estàndard o cas dels interface del Java referits al tipus que els implementi). Les classes poden requerir operacions d'altres classes que cal esmentar com a requeriment de context (requeriment de visibilitat d'una instància de la classe per al tipus en el context d'ús) (en el Java s'esmentarien a les clàusules extends o bé implements). Vegeu #Encapsulament estil O.O..
Els tipus poden aportar implementacions específiques de la signatura d'una classe o incorporar les implementacions per defecte definides a la classe.
No hi ha l'herència pare/fill com entre les classes de la O.O. estalviant el temps esmerçat en el despatx per taula de mètodes virtuals (vtable) i els conflictes de l'herència.
Les implementacions poden establir requeriments de context per a les variables de tipus, addicionals als establerts a la signatura.
Vegeu exemple

### Col·leccions heterogènies

Les llistes són de tipus homogenis. Per encabir elements de tipus divers per un tractament comú, cal caracteritzar-los amb un tipus existencial que admeti components d' aquells tipus que implementin la interfície que inclogui l'operació que s'hi vol aplicar.

### Variables

Haskell disposa de variables globals IORef's similars a les ref del ML Estàndard, i variables STRef's d'àmbit local per encapsular actualitzacions destructives.
Per al cas de sincronització blocant, Haskell fa servir com a variables de modificació sincronitzada el mecanisme de comunicació per bústies on una MVar és una bústia d'un sol element. Les operacions sobre la bústia són posar i treure. Al retirar un element de la bústia, la gestió de memòria de l'element queda en l'àmbit del procés que l'obté. Per consultar-ne el contingut l'has de treure, deixant la bústia buida. Per al cas de comunicació amb encuament, Chan i BoundedChan són bústies amb encuament i blocatge.
Per la concurrència amb memòria transaccional per programari (STM), hi ha les variables transaccionals TVar, TMVar (MVar's protegides per transaccions) i bústies TChan.

### Efectes col·laterals

Una acció amb efecte (un canvi) pot produir, a més, un resultat computable (per ex. l'entrada de consola: getline). El tipus de l'efecte vindrà parametritzat pel tipus del resultat.
El més emprat és l'efecte global IO (engloba entrada/sortida, variables globals IORef's i tractament d'excepcions) i el tipus d'una acció d'efecte global serà (IO tipusDelResultat).
Vegeu #Efectes

### Composició d'efectes

Per a les mònades vegeu Transformadors de mònades.
L'equivalent per a les fletxes són els Arrow Functors. Vegeu doc. "Generalizing Monads to Arrows".

## Lèxic
### Identificadors

Un identificador consisteix en una lletra seguida de zero o més {lletra, dígit, guió baix, o bé apòstrof}. L'especificació no fa esment de límits en la llargada dels identificadors.
Haskell98 admet caràcters no anglosaxons als identificadors segons la codificació Unicode. S'admeten caràcters accentuats, la ç, l'apòstrof, el caràcter l· (ela geminada), si el podeu compondre (AltGr+L al Linux), però no el punt volat (ang:mid dot) (·) considerat com a separador.
L'apòstrof també pot formar part del nom, per a un ús amb estil matemàtic
, però també com a part interna d'un identificador.
A l'intèrpret GHCi sobre Linux/Ubuntu amb LANG=ca_ES.UTF-8:
La pragma {-# LANGUAGE UnicodeSyntax #-} permet la substitució de determinades seqüències per caràcters Unicode equivalents.

#### ent/sort. amb caràcters no anglosaxons

    A partir de la versió 6.12.1, el compilador GHC incorporarà la codificació de caràcters del sistema subjacent per al tractament d'ent./sort. de les tires de caràcters.
    Si no disposem d'aquesta versió podem tractar fitxers UTF-8 amb el paquet utf8-string.

### Grafia
#### començant per lletra

* cas de primera lletra minúscula, indica variable (de valor o de tipus segons el context)
* cas de primera lletra majúscula, indica constructor (de valor o de tipus segons el context)

#### començant per símbol
##### cas de guió baix

* patró comodí '_': patró irrefutable quin valor encaixat no interessa per al càlcul
* patró comodí amb identificador _abc123 : quan una variable no es fa servir però s'hi manté per documentar, el guió baix precedint la variable no utilitzada evita que el compilador mostri un missatge d'atenció (Warning) per inútil.

##### començant per ':' (caràcter dos-punts)

    constructors no alfanumèrics binaris definits per a ser emprats en posició infix segons la definició de sintaxi del Haskell, per exemple:
* (:) constructor cons de llistes (ex.: cap : cua)
* (:+) constructor de nombres complexos (ex.: part_real :+ part_imag)
* (:.) constructor de dimensions i d'índexs per a vectors pluridimensionals (ex.matriu 3x3: (Z:. 3 :. 3)) al paquet Repa

##### començant per '?'

    variables que es passen com a paràmetres implícits (associables a l'àmbit de la funció que ha fet la crida, semblant al pas de paràmetres per referència del lleng. C) amb l'extensió ImplicitParams

##### començant per altres símbols

    operadors

## Sintaxi

Vegeu. produccions sintàctiques del Haskell2010.

### comentaris
#### comentaris d'autodocumentació

Comentaris per ésser extractats a un resum mitjançant el programa haddock amb comentaris de blocs entre delimitadors {-| -} i comentaris de línia precedits per -- <comanda>
Els comentaris admeten llenguatge de marcatge (els delimitadors en determinen el tractament):
* invocació per generar documentació (per la sortida en html: opció -h):
En el cas molt probable que hi hagi símbols enllaçats definits en altres paquets sortiran missatges de manca d'enllaç amb la documentació dels altres paquets
Per evitar-los cal generar enllaços a la doc. dels altres paquets, esmentant per cada paquet l'opció --read-interface (-i) amb el camí de la doc i el fitxer d'interfície "haddock" (extensió: .haddock) (que es pot generar amb l'opció --dump-interface) per exemple:

### Espais de noms

Hi ha sis menes de noms que constitueixen espais independents (es pot fer servir el mateix identificador per al que convingui en cada espai)
* variables
* constructors de dades (els de la dreta de l'assignació en una instrucció data)
* variables de tipus
* noms (constructors) de tipus
* noms de classes de tipus
* noms de mòdul
Un mateix identificador no pot ser emprat com a constructor de tipus i com a classe en el mateix àmbit.
Exemples de possible confusió:
* L'identificador ArithException és un constructor (dins el tipus Exception de H98) i també un nom de tipus ArithException
Vegeu-ho aquí
És habitual fer coincidir el nom del tipus i el del constructor, en una clàusula data d'un únic constructor, o bé en una clàusula newtype.

### definició de blocs

De dues maneres possibles:
* La compacta, blocs definits per claus i separant les instruccions per punt-i-coma class Eq t where { (==) :: t -> t -> Bool ; (/=) :: t -> t -> Bool } -- a l'intèrpret ghci Prelude> let { incr :: Int -> Int ; incr x = x + 1}
* L'elegant, blocs definits per la profunditat del sagnat (marge esquerre). Els punt-i-coma al final de línia es poden estalviar. Substituint les claus '{', '}' de l'exemple anterior per salts de línia amb augment o disminució del sagnat: class Eq t where (==) :: t -> t -> Bool (/=) :: t -> t -> Bool -- a l'intèrpret ghci, amb el mode multilínia :{ :} Prelude> :{ Prelude| let incr :: Int -> Int Prelude| incr x = x + 1 -- cal alinear els blocs 'let' al primer identificador Prelude| :} Prelude>
Per fer macros de CPP convé fer servir la sintaxi de claus, doncs les macros no generen salts de línia.

### Funcions binàries en posició infix en expressions

Qualsevol funció de dos o més operands es pot emprar en posició infix (entremig) si posem el seu nom entre cometes revesses entre el primer i el segon, fetes amb la tecla de l'accent greu seguida de la tecla espai. En anglès s'hi refereixen per backquotes
Els noms en infix admeten declaracions d'associativitat i precedència, per defecte màxima precedència i associativitat per l'esquerre. Els noms d'operacions habituals usats en infix que no tenen altre operador (`div`, `mod`, ...) tenen assignades l'associativitat i precedència del grup d'operacions al qual pertanyen.

### operadors d'aplicació ($) i (&)

L'operador d'aplicació ($) és molt freqüent i estalvia parèntesis en aplicar una funció a una expressió de més d'un terme.
* excepte quan el paràmetre és una funció polimòrfica sense declaració de tipus, perquè ($) és una funció amb polimorfisme de rang 1 i no admet funcions polimòrfiques com a paràmetres, com s'explica a la ref.
* ($) té la menor de les precedències dels operadors i associativitat per la dreta.
Quan el nombre d'aplicacions amb ($) passa de dues es complica copsar el sentit de l'expressió i és preferible utilitzar l'aplicació cap enrere (&) obtenint un estil de navegació de dades.
* Hi ha un altre ús de $ com a prefix a GHC (prefixant l'identificador com $identif, o bé prefixant el parèntesi com $(expr)) per avaluar un identificador o bé una expressió en temps de compilació.

## Tipus i classes

El tipus indica únicament el domini.
Les classes de tipus designen un grup d'operacions que un tipus pot implementar. La paraula reservada class introdueix un mòdul genèric de signatures d'operacions, indexat pel paràmetre de tipus, amb possible implementació per defecte de les operacions.
Les classes de tipus només poden contenir signatures i implementacions de funcions que facin ús del paràmetre de la classe.
Les classes de tipus s'assemblen als mòduls genèrics de l'Ada amb un paràmetre de tipus, amb l'exclusió de tot allò que no faci ús del paràmetre de tipus del genèric (la classe); també es poden assimilar als Interface de Java assimilant el paràmetre de tipus al tipus de l'objecte Java que els ha d'implementar.

### classes i clàusula deriving

La clàusula deriving demana al compilador que derivi instàncies (implementacions) de classes bàsiques a partir de les representacions internes dels tipus. Aquestes classes són:
| classe | requeriment de context (requereix visibilitat d'instàncies de les classes esmentades en l'àmbit d'ús) | descripció | operacions afegides |
| Eq α | | Igualable | (==) (/=) |
| Ord α | Eq α | Ordenable | (<), (<=), ..., (compare: amb resultat ternari Ordering), (max), (min) |
| Enum α | | Enumerable | (succ: successor) (pred: predecessor) (fromEnum α: enter ordinal corresponent) (toEnum n :: TipusEnumerat: enumerat corresponent a l'enter ordinal, la restricció de tipus indica el domini, defineix una Successió) |
| Bounded α | | Acotat | (minBound::TipusAcotat: cota inferior, la restricció de tipus indica el domini) (maxBound::TipusAcotat: cota superior) |
| Ix α | Ord α | Indexador | (index: índex basat en 0), (inRange), (rangeSize), (range: llista compresos) |
Classes {Show, Read} per la representació textual de dades numèriques:
| classe | descripció | operacions |
| Show α | Textualitzable a String | (show), (showList), (showsPrec). |
| Read α | Llegible des de String | (readList), (readsPrec) |
* Els caràcters no ASCII (quina repr. depèn de la codificació) en un tipus String es mostren amb un codi numèric:
* Per la manipulació de texts no anglosaxona, cal fer servir el tipus Text del paquet del mateix nom (encapsula un vector de caràcters codificat segons UTF-16).
* el mòdul Numèric proporciona un ventall més ampli de conversions entre text i nombres.
Classes de tipus numèrics:
| classe | requeriment de context | descripció | operacions afegides |
| Num α | | Numèric, estructura d'Anell unitari | op. binaris: (+), (-), (*) literals elements neutres: 0, 1 op. unaris: (negate: invers de la suma), (abs), (signum: retorna {-1,0,1}); llei: {abs x * signum x == x} (fromInteger: per decodificar literals enters o convertir de precisió il·limitada) |
| Bits α | Num α | Adreçable als bits | (.&. :i), (.|. :o), xor, complement, shift, rotate, ... |
| Real α | (Num α, Ord α) | Estructura d'Anell unitari ordenat | (toRational: obtenció de l'aproximat Racional, ex.: toRational $ sqrt 2) |
| Integral α | (Real α, Enum α) | Íntegre; Estructura d'Anell unitari ordenat i euclidià | {(div), (mod), (divMod)} -- divisió partint cap a menys infinit euclidiana {(quot: quocient), (rem: romanent), (quotRem)} -- divisió partint cap a zero NO euclidiana (toInteger: a sencer de precisió il·limitada) |
* Classes per al suport de racionals i reals.
| classe | requeriment de context | descripció | operacions afegides |
| Fractional α | Num α | Fraccionable (estructura de cos) | (recip: recíproc, invers del producte), (/), (fromRational: per decodificar literals amb part decimal o convertir de racionals de precisió il·limitada) |
| RealFrac α | (Real α, Fractional α) | estructura de cos ordenat / info sobre fraccions | (truncate), (round), (ceiling: (sostre) menor sencer superior), (floor: (terra) major sencer inferior), (properFraction: fracció pròpia) |
| Floating α | Fractional α | estructura de cos amb càlculs en coma flotant, logaritmes i trigonometria | (sqrt), (**: exponenciació), (exp), (log: logaritme natural), (logBase), (pi), (sin), (cos), (tan), (asin), (sinh), (asinh), ... |
| RealFloat α | (RealFrac α, Floating α) | estructura de cos ordenat / info dels reals en coma flotant | (significand: signe * valor de la mantissa (interval obert [0.5 .. 1))), (exponent: segons l'equació: r == (significand r) * (2 ^^ (exponent r))); 1 == 0.1$_{base_2}$ * 2^^1 -- no correspon a l'exponent de la notació científica!! (isNaN: és No-Numèric?), (isInfinite: resultat de sobreiximent?), (isDenormalized: és nombre subnormal (d'exponent inferior al mínim)?), ... |
Les operacions dels racionals, per la seva especificitat, no estan definides com a classe. Són en un mòdul a banda. El tipus està parametritzat pel tipus dels components del parell (numerador, denominador).
* (Ratio a): Ops. dels racionals: (%: op. generador) (numerator), (denominator), ..
Els reals de Coma fixa estan definits al mòdul Data.Fixed
GHC estén el mecanisme de derivació d'instàncies a algunes classes més. Vegeu ref.

#### Tipus

bàsics :
| tipus | constructors / =expr | mòdul | descripció |
| -- Unit -- tipus d'un únic valor | | Prelude | resultat buit en efectes col·laterals (ex.: print "abc" :: IO) equival al "void" o buit del llenguatge C |
| Bool | True | False | Data.Bool | Nombres booleans (Cert | Fals) |
| Ordering | LT | EQ | GT | Data.Ord | (Menor | Igual | Major) resultat ternari de (compare) |
| Char | | Data.Char | caràcters de 32 bits amb codificació Unicode |
| String | = [Char] | Data.Char Data.String | llista de caràcters |
El tipus String no és el millor per al tractament de text: show string mostra els caràcters no anglosaxons imprimint el codi numèric, cosa que s'utilitza per a la serialització de dades i la seva recuperació gràcies a la representació unívoca independent de la codificació. Les ops. d'Entrada/sortida sí que n'ofereixen la representació segons la codificació del sistema subjacent.
El tipus Text del paquet text (ve amb les biblios de la Plataforma Haskell), està implementat com a vector de caràcters UTF-16 i té millor suport per la manipulació de textos i l'entrada/sortida que es mostra segons la codificació del sistema subjacent.
numèrics :
| tipus | requeriment de context | constructors / =expr | mòdul | descripció |
| Int, Int<N> N∈{8,16,32,64} | | | Data.Int | Sencers (aritmètica del "Complement a dos") (cas de Int: rang mínim [-2^29 .. 2^29-1]) |
| Word, Word<N> N∈{8,16,32,64} | | | Data.Word | Paraula de bits: Adreça de memòria o valor natural, segons amplada paraula ordinador, (aritmètica modular, mòdul 2^nombre_de_bits) -- cas concret: op. (negate) vàlida (Word instancia Num); al ghci: Prelude> Numeric.showHex (-(2::Word)) "" "fffffffffffffffe" |
| Integer | | | Prelude | Sencer de precisió il·limitada |
| Natural | | | Numeric.Natural | Natural de precisió il·limitada -- cas curiós: op. (negate) vàlida (Natural instancia Num); al ghci: Prelude Numeric.Natural> -(10::Natural) *** Exception: arithmetic underflow |
| Float, Double | | | Prelude | Coma flotant |
| Ratio t | Integral t | Generador: (%) numerador % denominador | Data.Ratio | Racionals genèrics (t * t): parells (numerador, denom.), per a tipus t amb estructura d'anell íntegre euclidià |
| Rational | | = Ratio Integer | Data.Ratio | Racionals (Integer * Integer) |
| Uni, Deci, Centi, Milli, Micro, Nano, Pico | | | Data.Fixed | Coma fixa de representació sencera valor = representació * resolució del tipus |
| Complex t | RealFloat t | = !t :+ !t | Data.Complex | amb constructor infix (:+) i prefix '!' d'avaluació estricta als components |
efectes :
| tipus | constructors / =expr | mòdul | descripció |
| Maybe t | Nothing | Just x | Data.Maybe | * efecte fallada (resultat opcional en operacions parcialment definides) * paràm. opcionals |
| Either tipError tipResultat | Left error | Right resultat | Data.Either | * efecte fallada amb indicació de l'error * paràm. dual Right (dreta o correcte) o Left (esquerre o mancat) * Èxit o fracàs de l'avaluació amb try de codi que pot llançar excepcions capturant l'excepció que retorna amb Left o el resultat amb Right. |
| tipElement |, (x : xs), [x], [1,2,3], [1..7], [1,3..7] (==[1,3,5,7]) -- llistes infinites: [1..], [1,3..] | Data.List | * llistes * efecte múltiple (resultat múltiple en operacions) |
| IO tipResultat | | System.IO, Data.IORef, Control.Exception | * operacions d'entrada/sortida, * lectura/escriptura de variables globals IORef (cicle de vida no acotat), * tractament d'excepcions. |
| ST s tipResultat | | Data.STRef Control.Monad.ST | * lectura/escriptura de variables amb vida limitada a un àmbit * encapsulament d'actualitzacions destructives de les variables STRef avaluables en un espai s local (runST) o bé global (stToIO) |
excepcions :
| tipus | requeriment de context | constructors / =expr | mòdul | descripció |
| IOError | | | System.IO.Error | Excepció en expressions IO |
| Exception | | | Control.OldException | tipus algebraic d'error del Haskell98 obsolet—la nova classe Exception permet construir excepcions amb tipus definits per l'usuari. |
| SomeException | Exception e | SomeException e | Control.Exception | nou tipus genèric de les excepcions definit existencialment com un tipus d'aquells que implementen la classe Exception |
altres :
| tipus | constructors / exemples | mòdul | descripció |
| (t1,t2,...,tn) | (,) t1 t2 (,,) t1 t2 t3 (,,...,) t1 t2 .. tn | Data.Tuple | tipus producte anònim (tupla) |
| data nomDeTipus | Constructor t1 t2 .. tn deriving <classes a instanciar automàticament> | | tipus producte amb nom la clàusula "deriving (Eq, Show, ..)" demana al compilador que generi instàncies de les classes bàsiques esmentades partint de la representació interna |
| data nomDeTipus | Dl | Dt | Dc | Dj | Dv | Ds | Dg deriving (Eq, Show, Ord, Enum, Bounded) | | Enumeració (de constructors d'aritat 0) |
| data nomDeTipus | Constructor1 t11 t12 .. t1n | Constructor2 t21 t22 .. t2m | ... deriving ... | | tipus suma (Unió discriminada) |
| data nomDeTipus | Constructor {camp1 :: t1, camp2,camp3 :: t2i3, ...} | | Registres (tipus producte amb accessors) |
| newtype nomDeTipusDerivat | Constructor nomDeTipusBase deriving <classes preservades> o bé: Constructor {accessor :: nomDeTipusBase} deriving ... | | tipus derivats d'un tipus base, * el Constructor constitueix un morfisme del tipus base al derivat, mantenint l'estructura de les classes esmentades a la clàusula deriving quines instàncies hereta el tipus derivat * l'accessor, si hi és, constitueix el morfisme invers del Constructor |
* classes que implementen (a banda de Eq, Show i Read)
bàsics :
| | Ord | Enum | Ix | Bounded |
| | ordenable | enumerable | indexador | acotat |
| -- Unit -- equival al void del C | Sí | Sí | Sí | Sí |
| Bool | Sí | Sí | Sí | Sí |
| Ordering | Sí | Sí | Sí | Sí |
| Char | Sí | Sí | Sí | Sí |
numèrics :
| | Ord | Enum | Ix | Bounded | Num | Bits | Real | Integral | Fractional | RealFrac | Floating | RealFloat |
| requereix | Eq | | Ord | | | Num | Num, Ord | Real, Enum | Num | Real, Fractional | Fractional | RealFrac, Floating |
| descripció | ordenable | enumerable | indexador | acotat | Numèric | adreçable als bits | Real | íntegre amb divisió euclidiana | fraccionable | infos. de fraccionables | càlculs i trigonometria | infos. de coma flotant |
| estructura | ordre total | Successió | Successió | Ordre total finit | anell unitari | vector de bits | anell unitari ordenat | anell unitari ordenat euclidià | estructura algebraica de cos | estruct. de cos ordenat | estruct. de cos | estruct. de cos ordenat |
| Int, Int<N> aritmètica del complement a dos | Sí | Sí | Sí | Sí | Sí | Sí | Sí | Sí | No | No | No | No |
| Word, Word<N> aritmètica modular | Sí | Sí | Sí | Sí | Sí | Sí | Sí | Sí | No | No | No | No |
| -- precisió il·limitada Integer, Natural | Sí | Sí | Sí | No | Sí | Sí | Sí | Sí | No | No | No | No |
| -- coma flotant Float, Double | Sí | Sí | No | No | Sí | No | Sí | No | Sí | Sí | Sí | Sí |
| Rational | Sí | Sí | No | No | Sí | No | Sí | No | Sí | Sí | No | No |
| -- coma fixa Uni, Deci, Centi, Milli, Micro, Nano, Pico | Sí | Sí | No | No | Sí | No | Sí | No | Sí | Sí | No | No |
| Complex t | No | No | No | No | Sí | No | No | No | Sí | No | Sí | No |
Vegeu també:
* contenidors

##### El cas dels tres operadors d'exponenciació

El domini de l'exponent determina el context del domini d'aplicació per les operacions requerides:

##### literals

Els literals numèrics no s'associen a tipus. Sense punt decimal requereixen que el tipus tingui estructura d'anell unitari (implementi la classe Num), mentre que els nombres amb part fraccionaria o notació exponencial (ex.: 5E2) requereixen que el tipus tingui estructura algebraica de cos (implementi la classe Fractional).
El signe menys no forma part del literal, s'interpreta com a operador (unari si és al capdavant de l'expressió; binari si la posició és infix): (-1). Això no permet especificar els nombres negatius sense corresponent positiu: (-128)::Int8. L'extensió NegativeLiterals hi posa remei.
Amb l'intèrpret GHCi podem consultar el tipus d'una expressió amb
El tipus concret es determina:
* per l'operació on intervé, si el tipus del paràmetre és fix (en majúscula) o bé si és una variable de tipus en posició repetida
* explícitament, (1::Double)
* provant una seqüència de tipus (clàusula default)

###### literals amb notació científica

Des de GHC 7.8 els sencers poden tenir literals amb notació científica. Cal l'extensió de llenguatge NumDecimal

###### literals de llistes
##### conversions (casting de tipus)

Per la conversió, el tipus resultant serà el requerit per l'avaluació de l'expressió, exigible si cal mitjançant una restricció de tipus.
Les conversions funcionen com una caracterització de tipus (ang: cast) i no disparen excepcions si la precisió del tipus de destinació és menor que la d'origen.
Les conversions entre Int i Word preserven la representació (no pas el signe).
* conversions des de tipus amb precisió il·limitada o indefinida (per ex. literals amb seqüència de dígits de llargada indeterminada):
* conversions
Exemples:
* Des de Íntegre (ang:Integral) Anell ordenat euclidià segons la def.
* Des de Real (anell ordenat): són instància de Real els Float, Double, Int, IntN, Integer, Natural, Word, WordN, Racionals i els de Coma fixa.
* Amb Racionals : (% és el constructor dels racionals. Ha d'anar entre espais, però la viquipèdia el retalla si va precedit d'un nombre)
fromRational és membre de la classe Fractional (Fraccionable, estruct. de Cos).

#### tipus algebraics

Creats amb la clàusula data: Enumeracions, tipus producte, tipus suma, ...

##### enumeracions

Unió de constructors d'aritat 0 (sense paràmetres) quina definició estableix un conjunt amb un ordre seqüencial. El compilador facilita la derivació de classes específiques si les explicitem a la clàusula deriving:
* Show: per a la conversió a String
* Eq: per a la distinció
* Ord: relació d'ordre
* Enum: {(succ: successor) (pred: predecessor) (fromEnum: enter ordinal corresp.) (toEnum: enumerat corresp. a l'enter ordinal)}
* Bounded: cotes inferior i superior

##### Tipus producte

* El constructor equival a un morfisme del producte dels components (per ex.: Int * Int) al tipus nou.
* De fet, a GHC, l'extensió GADTs, permet descriure els constructors com a funcions:
Encaix dels paràmetres discriminant pel constructor si n'hi ha diversos.

###### Registres

Augmenta el tipus producte, especificant noms de camps com a funcions accessores als components. No hi ha registres anònims (cal distingir-los pel constructor).
Els registres corresponen en la P.O.O als objectes i els seus camps, mentre que el comportament es materialitza en les instàncies (implementacions) de les classes de tipus (interfícies).
* Definició: data Tipus = CRec {camp1 :: tipus1, camp2, camp3 :: tipus2i3}
* Inicialització de valors: Cas de fer servir el literal de camps, aquests hi han de ser tots. També podem utilitzar el constructor com al tipus producte, sense els noms de camp, amb els components en l'ordre especificat a la definició.
* Literal dels camps als patrons (només cal especificar els parells (camp = patró) que interessin):
* Literal dels camps a l'actualització
* El literal dels camps "{campA=x}" està lligat sintàcticament al terme precedent amb major precedència que l'operació d'aplicació, tant en patrons com en cas d'actualització. No caldrà agrupar-los:
* Espai de noms: Els noms dels camps pertanyen a l'espai de noms del mòdul i convé afegir-los-hi un prefix per evitar col·lisions. L'extensió DuplicateRecordFields (GHC 8.0) permet la coincidència de noms de camps entre registres d'un mateix mòdul, sempre que el seu ús sigui inambigu (fent servir restriccions de tipus quan calgui), i la seva exportació es faci com a símbol intern del tipus.
Per la sintaxi simplificada a GHC vegeu
Cas de registres niuats o bé camps estructurals, les referències funcionals anomenades lents ofereixen la possibilitat de consulta i modificació d'estructures complexes

###### Reversibilitat de tipus en registres d'un sol component

És una construcció força utilitzada per què en aquests registres, el constructor i l'accessor són funcions inverses l'una de l'altra.
Vegeu també més avall #Tipus derivats -- newtype

###### Tuples

tipus producte anònim amb constructors com: (,); (,,); .... Ops. definides a Data.Tuple

##### tipus suma

Unió de tipus discriminada per etiquetes (constructors), seguits dels tipus dels components

###### Registres variants i accessors parcials

Els accessors no definits per tots els constructors, són funcions parcials (poden fer petar el programa)
* Una alternativa és no fer servir els noms de camp com a accessors, sinó només en patrons, però els resultats incerts dels camps no comuns mostren que no és un bon disseny.
* És millor fer-ne tipus diferents per cada cas, definint setZ només per al tipus 3D. Per un tractament comú dels camps comuns caldrà definir getters/setters en classes i instanciar-les per a ambdós tipus.

###### Polimorfisme de registres amb camps específics - la classe HasField

    Des de GHC 8.2 ja no caldrà classes "getters" per aconseguir polimorfisme sobre els accessors comuns.
      * requeriment d'existència d'accessor de nom "camp": HasField "camp" tipusRegistre tipusCamp

##### tipus polimòrfics

Amb variables de tipus (els identificadors que comencen per minúscula).
* Maybe (paràmetres i resultats opcionals).
* Either (èxit o fracàs de l'avaluació d'una acció que llança excepcions, retornant Left amb l'excepció o bé Right amb el resultat).
Els tipus que no inclouen variables de tipus s'anomenen monomòrfics.

#### sinònims de tipus

Els sinònims de tipus són com macros al nivell de tipus.

##### sinònims paramètrics

El següent sinònim inclou paràmetres de tipus.

#### llistes

El tipus Llista (seqüència d'accés lineal), amb constructors "" (llista buida, anomenat nil) i ":" (tip_elem * llista_elem, anomenat cons) Operacions al mòdul Data.List
Més operacions a contenidors

##### llista per comprensió

Especifica l'expressió objectiu, obtenint-ne els valors de les variables d'una seqüència de generadors i filtres separats per comes

###### llista per comprensió monàdica

La llista per comprensió precedent es pot expressar amb un bloc monàdic
Vegeu-ho a Mònada (programació funcional)#Llista per comprensió monàdica

###### llistes per comprensió a l'estil de SQL

L'extensió de GHC TransformListComp permet incorporar-hi transformacions. Vegeu exemple.

#### tires de text

-- el tipus String (cat: corda o enfilall d'objectes, indica seqüència, aquí en direm tira com les tires de números consecutius de les rifes) és una llista de caràcters i és el tipus de les tires incloses al codi. String no és definit com a estructura (data) sinó com a àlies o sinònim (type) de l'expressió:
* Llegiu l'article "How to pick your string library in Haskell"
L'extensió OverloadedStrings permet fer servir literals de tipus String com a valors de tipus que n'implementin la conversió, instanciant la classe IsString.

##### Tires de text implementades amb vectors - El tipus Text

Tires com a seqüències d'accés aleatori, a diferència de String definit com a llista (seqüència d'accés lineal)
* amb un tipus text que empaqueta els caràcters en un vector de UTF-16, definit a la biblioteca "text"
Estructura del tipus Text que és un tipus opac (l'estructura és només d'ús intern):
Exemple d'ús:
compilant amb preprocés (opcions -cpp o bé -XCPP o bé {-# LANGUAGE CPP #-} al codi)

##### Sobrecàrrega de literals String i llista

L'extensió de llenguatge OverloadedStrings facilita que, de manera similar als literals numèrics, els literals de tires de caràcters admetin també l'assignació del tipus requerit per l'operador, sempre que el tipus de l'operand proporcioni la conversió, implementant fromString de la classe IsString.
De manera similar, des de GHC 7.8 amb l'extensió OverloadedLists, els literals llista també poden prendre tipus d'altres col·leccions que n'implementin la conversió instanciant la classe IsList. Vegeu Compilador Haskell de Glasgow#Sobrecàrrega de literals Llista
| | literals i decodificació | literals i decodificació | literals i decodificació | literals i decodificació |
| literal | classe | funció decodificadora o de conversió | extensió de llenguatge requerida | exemples |
| 999 (* sense parts decimal/exp. *) 0xFF, 0o377 | Num | fromInteger | | |
| 999[.99] [E[±]999] (* notació científica *) | Fractional | fromRational | | 2.5E-2 :: Rational 2.5E-2 :: Float |
| 999[.99] [E[±]999] (* notació cient. avaluable a enter *) | Num | fromInteger | NumDecimals | 2.5E2 :: Int |
| 0b11001100 | Num | fromInteger | BinaryLiterals | |
| "tira de caràcters" | IsString | fromString | OverloadedStrings | "abc" :: Text |
| '[' 1,2,3 ']' (* seq. de valors *) | IsList | fromList | OverloadedLists | [1, 3..9] :: Set Int [(1,"a"), (2,"b")] :: Map Int String |

## Expressions
### funcions

A la declaració cal especificar els tipus dels paràmetres separats per fletxes; si son genèrics en minúscula
* la repetició d'una variable de tipus a la signatura, indica que el tipus corresponent a les aparicions repetides d'una mateixa variable ha de coincidir amb el tipus encaixat en primera posició.
Qualsevol importació d'un mòdul importa totes les instàncies exportades (visibles a nivell de mòdul)

#### Funcions anònimes anomenades Expressions lambda

La barra invertida, caràcter del teclat que més s'assembla a la lletra grega lambda (per referència a l'abstracció lambda del càlcul lambda, fonament de la programació funcional), introdueix una funció anònima com a expressió.
és equivalent a
És una notació importada del càlcul lambda on $\lambda x.\lambda y.\lambda z.E$ s'abreuja com a $\lambda xyz.E$
Cal tenir en compte que el cos de la lambda abasta el màxim cap a la dreta
* L'extensió de llenguatge LambdaCase permet obviar la variable quan introdueix un case.

#### Aplicació parcial

Vegeu ref.
L'aplicació parcial d'un paràmetre actual a una funció causa la substitució de la variable pel paràmetre en l'expressió, resultant una funció de les variables restants.
Per la reducció beta del càlcul lambda $((\lambda x.E)\ E')$ és la substitució $E[x:=E']$.
L'aplicació és associativa per l'esquerra. f x y ≡ (f x) y
L'operador de funció (->) "retorna" és associatiu per la dreta:

#### Pas de paràmetres

Per defecte: per necessitat (ang: lazy) = avaluació tardana (quan se'n requereix l'ús) amb substitució de l'avaluació del thunk de l'argument, i memoïtzació del resultat de l'avaluació de l'argument.
El mode d'avaluació del paràmetre es pot alterar amb un prefix al patró segons la taula següent:
| extensió | prefix als patrons dels paràmetres formals | avaluació | comentaris |
| -- per defecte | patró | lazy (avaluació per necessitat call by need) | |
| -- per defecte | ~patró | aval. tardana i irrefutable de l'encaix | Vegeu Avaluació tardana explícita de l'encaix |
| BangPatterns -- afegeix sintaxi prefix '!' | !patró | estricta, per valor | |
| Strict -- modifica la semàntica | patró | per defecte: estricta i per valor | |
| Strict -- modifica la semàntica | ~patró | lazy (avaluació per necessitat call by need) | |
Vegeu extensions BangPatterns i Strict

##### Pas de paràmetres per valor

Vegeu #Avaluació estricta explícita, passar per referència.
L'especificació d'estrictesa als paràm. formals requereix l'extensió BangPatterns o bé la Strict.
L'extensió de llenguatge Strict de GHC 8.0 capgira el mode d'avaluació dels patrons, on per defecte l'avaluació serà estricta (excepte per als identificadors a nivell de mòdul "Top level bindings"), assenyalant el pas de paràmetres tardà (lazy) amb (~).

#### Àmbit dinàmic - paràmetres implícits

Permet lligar variables amb prefix '?' a l'àmbit del procediment que fa la crida, com el pas de paràmetres per referència del lleng. C, sempre que s'especifiqui la variable en un requeriment de context (requereix visibilitat en l'àmbit de la crida).
* Cal esmentar-les als requisits de context per fer referència a l'àmbit d'origen.
* Cal l'extensió de llenguatge {-# LANGUAGE ImplicitParams #-}. Vegeu ref.

#### Explicitar un tipus amb el paràmetre Proxy

El tipus (Proxy a) és un tipus de paràmetre que no comporta dades, i s'utilitza per fer coincidir un tipus amb el de paràmetres subseqüents.
Exemple d'ús en l'entorn Servant.

#### Funcions d'ordre superior

Quan algun dels paràmetres és una funció:
Els operadors bàsics sobre funcions són al mòdul Data.Function
Al passar un paràmetre funció no se'n comprova l'aritat.

##### Secció (tall) d'un operador en infix

La secció d'un operador en infix consisteix en convertir una expressió d'un operador binari en una funció anònima d'un dels operands, que s'omet i es tanca entre parèntesis, per exemple (< 5). Vegeu ref.
* excepte el cas (-1) doncs el signe menys a l'inici d'expressió es considera operador unari.

#### Patrons i guardes
##### casuística per encaix de patrons dels paràmetres

El nom de la funció precedeix cada cas.
!! GHC no avisa quan els encaixos són incomplets (no exhaustius), excepte que ho demanis explícitament amb l'opció -fwarn-incomplete-patterns o -Wall
La determinació de si un encaix és viable s'avalua de manera estricta. Per a avaluar-los de manera tardana vegeu #Avaluació tardana explícita en els patrons d'encaix

##### l'operador (@) - assignació del valor encaixat a una variable

l'operador (@), anomenat as-pattern, com a (variable @ patró) unifica la variable i el valor encaixat al patró

##### Signatures de tipus als patrons

Totes les variables de patrons admeten signatures, quines variables de tipus han de pertànyer a l'àmbit de la definició.

##### Definició per Guardes

Definició de funcions basada en condicions

##### Definició per guardes de patrons

Haskell2010. (extensió de llenguatge PatternGuards) Permet condicionar una definició a una seqüència d'encaixos subordinats.
Quan volem donar categoria de definició a una expressió subjecta a una cascada d'encaixos
podem escriure la cascada d'encaixos en seqüència com a condicionant de la definició:

##### Sinònims de patrons

Des de GHC 7.8.1 amb l'extensió de llenguatge PatternSynonyms.
* Per al cas de patrons niuats, per distingir els patrons segons el component pretès amb noms més entenedors
* o també, per donar noms a valors als patrons
* hi ha dues sintaxis, segons l'ús pretès del sinònim:
   * unidireccional (<-) : circumscriu l'ús del sinònim al context de patrons.
   * bidireccional (=) : per emprar el sinònim tant en patrons i com en expressions.
* també poden estar definits dins una classe (associats), abstractes dins la classe, amb la definició concretada a les instàncies.

##### Patrons de vistes

S'entén per vista una funció d'un argument quin resultat es pot analitzar per patrons. La sintaxi (vista -> patró) es fa servir en el lloc d'un argument, aplicant la funció vista a l'argument i encaixant el resultat al patró. També es pot fer servir en un case o en una definició amb let. Extensió ViewPatterns.
* En una definició: f (vista -> patró) = … ≡ f v | patró <- vista v = …
* En un case: case v of { (vista -> patró) -> e1 ; _ -> e2 } ≡ case vista v of { patró -> e1 ; _ -> e2 }
Exemple a #Tipatge dinàmic - Paràmetres de tipus divers

#### Definicions d'àmbit local

Vegeu "Let vs Where".

##### amb where, estil declaratiu (ús abans de la definició)

    permet definir variables esmentades als patrons i guardes de la definició. Cada alternativa pot tenir el seu where.

##### amb let..in, estil imperatiu (definició abans de l'ús)

    cada (let .. in) estableix un àmbit on no s'hi pot redefinir un símbol, però es poden establir àmbits (let .. in) successius
Als blocs d'accions (efectes col·laterals) do, els subblocs let (que no duen la paraula reservada in al final) permeten definir expressions basades en resultats d'accions precedents

### Iteracions funcionals sense efectes col·laterals

Amb recursivitat els casos queden més clars de cara a assegurar-ne la finalització. Vegeu funció recursiva

### Operadors

* Associativitat especificant {infixl: per l'esquerra | infixr: per la dreta | infix: no associatiu}
* Precedència (0..9). Vegeu taula.
Per defecte: màxima precedència i associativitat per l'esquerra (infixl 9)

### operadors de funcions

Vegeu ref.
(.) composició:
($) aplicació normal (tardana) f $ x = f x. Permet estalviar parèntesis en aplicar operacions sobre el darrer paràmetre quan és una expressió (hi ha més d'un terme) o bé la part esquerra és una composició de funcions.
    Restricció: Hi ha objeccions a la seva aplicació en cas que el paràmetre o el retorn siguin funcions polimòrfiques que no tinguin declaració de tipus.

#### lectura de dreta a esquerra en la composició amb (.)

En aplicar una composició de funcions (f. g. h) obj sobre una variable o expressió, l'entendrem més fàcilment si les analitzem tenint en compte el tipus de l'objecte (domini) de l'aplicació i llavors les funcions que s'hi apliquen, començant per l'última de la composició, en sentit de dreta cap a l'esquerra.
Es pot escriure la composició a l'estil de flux de dades (d'esquerra a dreta), amb l'operador d'aplicació cap enrere (&) definit a Data.Function desde GHC 7.10.1

### Currificació

* curry: converteix una func. d'una Tupla2 en una que admet els paràm. separats
    + possibilita l'aplicació parcial de part dels paràmetres
* uncurry: conv. una funció de dos param. en una que els admet aparellats en Tupla2

### Traçabilitat dins el codi funcional

El codi funcional no permet l'ús de print (efecte col·lateral). Cal fer servir trace o bé traceStack del mòdul Debug.Trace. Imprimeix el primer paràmetre, via unsafePerformIO i retorna el segon.
Atenció: l'ordre d'execució de subexpressions en codi funcional és indeterminat, i igualment ho serà l'ordre d'impressió de les traces.
En codi monàdic (seqüencial), l'ordre d'impressió de les traces, està subjecte al moment de l'avaluació que, per ésser tardana, és difícil de predir amb seguretat.
A partir de GHC v.7.4.1 hi ha també traceStack :: String -> a -> a que a més bolca la traça de crides si s'ha compilat amb opcions de perfilat.
Substituïm trace per traceStack i ...

## Comportament: Classes de tipus

Els tipus només descriuen el domini de valors.
Les classes designen la interfície (signatures) d'un conjunt d'operacions, amb possible implementació per defecte, parametritzades pel tipus de la classe.
Les classes de tipus no són com les classes de C++, que són classes d'objectes, sinó com els Interface de Java, els genèrics de l'Ada o les signatures de ML.
Per utilitzar-les amb un tipus concret, cal generar una instància de la classe per al tipus definint-hi la implementació. Les instàncies visibles en l'àmbit, es passen implícitament a les funcions que les requereixen.
* Les instàncies no tenen identificació, no n'hi poden haver dues de la mateixa classe per al mateix tipus al mateix àmbit. Quan s'importa un mòdul s'importen totes les instàncies.
* Les instàncies no es poden tapar amb altres instàncies.
* Les instàncies s'han de definir en un dels mòduls on hi hagi, o bé la definició de la classe, o bé la del tipus, altrament seran etiquetades com a instàncies òrfenes i rebutjades pel compilador.
* L'única manera de redefinir instàncies és fer-ho sobre una derivació del tipus amb newtype, esmentant les altres instàncies a la clàusula deriving amb el mecanisme de l'extensió GeneralizedNewtypeDeriving que estalvia la redefinició d'instàncies.

### Especialització, instanciació per tipus

L'ús d'operacions que no són de la pròpia classe a les implementacions per defecte, fa necessari requerir la presència, en el context d'ús, d'instàncies de les classes que incorporen les operacions.
Vegeu exemple més complet més avall

#### Instanciació genèrica

Quan totes les operacions es basen en operacions de les classes base i no en particularitats d'un tipus, es pot definir la instanciació a nivell de classe amb efecte automàtic. (Requereix l'extensió de llenguatge UndecidableInstances).

#### Derivació d'instàncies per a tipus paramètrics amb requeriments

Amb l'extensió de llenguatge StandaloneDeriving el compilador permet que afegeixis requeriments de context a la derivació d'instàncies amb clàusules deriving independents de la definició de l'estructura.

#### Derivació ràpida d'instàncies de classes amb implementació per defecte

L'extensió DeriveAnyClass ho permet. Si Bar és una classe on tots els mètodes tenen implementació per defecte
es pot escriure en una sola línia (a banda de la pragma d'extensió de llenguatge)
Exemple a Compilador Haskell de Glasgow#serialització en format JSON

## Tipus derivats -- newtype

newtype defineix un tipus derivat d'un altre tipus (anomenat tipus base) amb possible herència de les instàncies de classes de tipus instanciades pel tipus base.
newtype defineix un tipus derivat mitjançant una estructura d'un únic component, el tipus base, mantenint la mateixa representació interna (el compilador esborra el constructor).
newtype defineix un morfisme (el constructor) del tipus base al derivat, que manté l'estructura de les classes que esmentem a la clàusula deriving heretant-ne, el tipus derivat, les instàncies. Si el newtype es defineix com a registre, l'accessor del camp constitueix el morfisme invers.
Per al cas de voler múltiples implementacions d'una classe de tipus (diverses relacions d'ordre o diversos monoides), com que les implementacions no tenen nom, cal definir un tipus derivat nou per cadascuna d'elles (vegeu exemple tot seguit).
L'extensió GeneralizedNewtypeDeriving permet que el tipus definit amb newtype hereti les instàncies de classes mono-paràmetre, esmentant-les a la clàusula deriving, més enllà de les quatre especificades per la versió Haskell98 del llenguatge (Eq, Ord, Enum, Bounded).
ús:
* Newtype també possibilita l'etiquetatge de tipus bàsics per evitar errors de transposició de paràmetres: "Keyword arguments in Haskell"

### ús dels newtypes predefinits

Els tipus All i Any definits amb newtype per als quals s'implementa un Monoide per a la conjunció o bé disjunció, permeten un tractament similar en definir els següents quantificadors de col·leccions basats en propietats.
Apliquem el constructor adequat (All o bé Any) als valors i el plegat amb monoide farà servir l'op. definida per al newtype corresponent. En acabat, caldrà convertir el tipus del resultat amb la inversa del constructor: l'accessor.

### tipus derivats de funcions

També s'utilitza per definir un tipus com a abstracció d'un tipus de funció. Això permet definir operacions de combinació de funcions del tipus específic, com a les Fletxes

## Col·leccions polimòrfiques
### Tipus existencial

El tipus existencial (contrari d'universal) designa tipus amb condicionants, i és un mecanisme de tipus per poder acomodar components de tipus divers que tinguin una interfície (operatòria, classe de tipus) en comú i així poder agrupar-los en col·leccions i tractar-ne els elements amb les operacions que comparteixen.
Vegeu El tipus existencial, originàriament és una mena de tipus abstracte, relacionat amb registres que poden prendre diverses formes concretes que se'n consideren subtipus, donant lloc a un conjunt de tipus.
* El compilador GHC utilitza la paraula reservada forall (quantificador ∀), per als tipus existencials apel·lant a un isomorfisme.
* Altres compiladors de Haskell fan servir la paraula reservada exists com a quantificador existencial, el EHC/UHC segons la ref., i el JHC també, en comptes del forall del GHC.
Tipificació més habitual, per exemple, objectes amb un component textualitzable (Show a)

#### quantificació existencial als registres

Vegeu ref.
      * No es permeten els camps quantificats existencialment en les actualitzacions de registres.
      * Cas de sintaxi GADT's els camps quantif. existencialment només poden aparèixer en actualitzacions, si la var. quantificada existencialment apareix individualment en el tipus resultat del Constructor, però no si hi apareix com a paràmetre, per exemple d'una llista.

#### quantificació existencial als àlies de tipus - sinònims liberalitzats

Admet restriccions existencials, a més d'altres possibilitats. Per aquells tipus 'b' tals que (Show b) ...

### Llistes homogènies d'elements amb components heterogenis

Vegeu. El #Tipus existencial permet definir tipus de dades polimòrfics amb components caracteritzats per admetre un mateix grup d'operacions.
D'aquesta manera es pot treballar amb llistes d'elements que incorporen components de tipus divers que implementin una mateixa classe de tipus, i tractar-los amb les operacions de la classe.
Cal especificar l'opció de compilació "-XExistentialQuantification" o la pragma {-# LANGUAGE ExistentialQuantification #-}
Vegeu-ne l'exemple #Col·leccions amb components heterogenis - Emulació del despatx dels mètodes virtuals de la O.O.

## Tipatge dinàmic - Paràmetres de tipus divers

Haskell admet pas de paràmetres amb control del tipus en temps d'execució, només per a tipus monomòrfics (sense variables de tipus).
Exemple amb l'ús de l'extensió ViewPatterns (Vegeu #Patrons de vistes)
dona

## Seqüències i col·leccions en codi funcional pur

Algunes de les funcions següents incorporen en la funció nucli de la iteració un paràmetre a l'entrada i a la sortida interpretable com a estat de la iteració, que evoluciona partint d'un valor inicial llavor per l'aplicació reiterada de la funció nucli.

### Seqüències - generació d'una seqüència partint d'un valor

És la particularització de Haskell d'un Anamorfisme o desplegament d'estructures: (b -> a*).
Amb la funció unfoldr ("unfold right", cat: desplega per la dreta) de Data.List. La seqüència s'acaba quan la funció nucli no retorna valor (Nothing).

### Seqüències - transformació d'una seqüència amb memòria

Amb mapAccumL de Data.List, podem especificar la funció nucli de la iteració, que partint d'un estat i un element de la seqüència ens proporcioni l'estat inicial de la següent iteració, i l'element de la seqüència de sortida.

### Col·leccions - reducció d'una col·lecció a un valor o bé estructura (plegat) - Les classes Foldable/Bifoldable i Monoid

És la versió de Haskell d'un catamorfisme o reducció d'estructures (a* -> b).
Cal especificar com a paràmetre la funció del plegat:
foldl de Data.List per a llistes ha estat substituïda en el mòdul Prelude per foldl de Data.Foldable per a col·leccions de tipus genèric.
Vegeu també iteracions a espai constant de la pila amb plegat per l'esquerra estricte
* La classe Foldable, del mòdul Data.Foldable, generalitza la reducció per a les col·leccions
* En cas que vulguem avaluació estricta, si l'acumulador és un tipus algebraic convé especificar avaluació estricta explícita als components de l'acumulador, altrament l'avaluació HNF deixa pendent d'avaluar les expressions dels components, engreixant la pila que pot petar de la mateixa manera que en els fold{l|r} no estrictes.

#### la classe Bifoldable

Des de GHC 8.2 el mòdul Data.Bifoldable proporciona, per a col·leccions d'elements de dominis duals, per ex. (Either a b), la possibilitat de reduir amb dues funcions de plegat, una per cada domini.
Per cada funció de Data.Foldable hi ha una funció corresp. de Data.Bifoldable anb el prefix bi.

#### Monoides per als plegats

* La classe Monoid, del mòdul Data.Monoid, facilita la definició de Monoides
* Podem necessitar diferents implementacions de Monoide (ex. per a la Suma i per al Producte), però les instàncies no tenen nom i, per tant, no es poden seleccionar. Cal crear tipus derivats amb newtype per cada instància addicional. El mòdul Data.Monoid en té uns quants de predefinits.
* Els tipus derivats amb newtype només poden tenir un sol component (el tipus base). Si estan definits com a registre, l'accessor ens proporcionarà la conversió inversa de la del constructor. No suposen cap sobrecost d'accés, doncs el compilador esborra el constructor.
Exemple. Plegat de la suma i el producte sobre una col·lecció de numèrics (Num t), utilitzant els "newtype" respectius:

### Col·leccions - composició - les classes Semigroup i Monoid

Des de GHC 8.0 s'ha incorporat al paquet base l'estructura Semigrup en un mòdul Data.Semigroup amb una operació associativa definida per (<>) amb associativitat infixr 6 <>.
Abans ja teníem la classe Monoid de Data.Monoid on mappend és l'operació associativa que en posició infix (`mappend`) processa associant per l'esquerra (assoc. per defecte: infixl 9), mentre que també es defineix (<>) com a sinònim que processa associant per la dreta (infixr 6 <>).
Exemple sobre llistes, conjunts i diccionaris (tots ells implementen les classes Semigroup i Monoid). Els vectors del paquet vector també.

### Col·leccions - aplicació als elements d'una col·lecció
#### La classe Functor

La classe Functor descriu una estructura de correspondències entre elements i contenidors que mapeja objectes a objectes i funcions a funcions mantenint la identitat dels objectes i la composició de les funcions en els dos dominis.
Un functor F és un homomorfisme que compleix:
   * $F(\mathrm {id} _{X})=\mathrm {id} _{F(X)}\,\!$ per a tot objecte $X$ del domini d'origen; en Haskell: fmap id ≡ id,
   * $F(g\circ f)=F(g)\circ F(f)$ per a tot morfisme $f:X\rightarrow Y\,\!$ i $g:Y\rightarrow Z$; en Haskell: fmap (g · f) ≡ (fmap g) · (fmap f)
Això possibilita substituir la composició d'aplicacions de morfismes ((fmap g) · (fmap f)), per l'aplicació de la composició (fmap (g · f) ). (Vegeu també desforestació).
L'operació fmap defineix la correspondència de funcions del domini dels elements al domini dels contenidors mitjançant l'aplicació d'una funció als elements de les col·leccions (ex.: [a]) o bé als resultats dels d'efectes (ex.: IO a) que l'instancien.
* Els conjunts no l'instancien:
Si la funció no és injectiva la imatge de diversos elements del domini origen pot coincidir, i en cas de tractar-se d'un conjunt, no preserva la mida de l'original, incomplint la regla de la composició com a l'exemple de la ref.
   * Tanmateix les implementacions de conjunts aporten la seva operació map particular, malgrat no implementar Functor.
* Els tipus monomòrfics (que no incorporen paràmetres, com ara Text, ByteString) tampoc. (El tipus ha de venir parametritzat amb el tipus de l'element)
   * El paquet mono-traversable aporta una solució vàlida per a totes les col·leccions siguin paramètriques o monomòrfiques, basada en classes genèriques i, per als tipus dependents, "tipus associats" (Index t, ContainerKey t, MapValue t) o bé #Famílies de tipus (Element t).

#### La classe Bifunctor

Des de GHC 8.2 el paquet base estén els Functors a les col·leccions d'elements amb domini dual (per ex.: Either a b) amb mapeig que incorpora funcions per cadascun dels dominis. Del mòdul Data.Bifunctor

#### Functors contravariants - la classe Contravariant

Quan el contingut del contenidor és una funció, es pot definir un Functor sobre el domini dels arguments (posicions contravariants) de la funció.
La covariança i contravariança es fa servir més als llenguatges que implementen subtipatge. Subtipatge, covariança i contravariança a Scala
Al paquet contravariant.

#### Profunctors

Un Profunctor és un Bifunctor que és contravariant en el domini del primer paràmetre de tipus i covariant en el segon.
Per tant, podem qualificar el primer paràmetre com a entrada, i el segon com a sortida (Les funcions en serien una instància donat que els paràm. d'una funció són contravariants i la sortida covariant).
Podem implementar els profunctors en tot allò que tingui un o més arguments (posició contravariant) del domini del primer paràmetre de tipus i un resultat (posició covariant) del segon paràmetre de tipus.
L'objectiu és poder aplicar simultàniament un contramap (funció incident) al domini contravariant (l'entrada) i un map (funció sortint) al domini covariant (la sortida), obtenint un nou profunctor sobre els dominis origen del contramap i el de destí del map.
Al paquet profunctors.
Exemple d'instàncies de Profunctors són
* les funcions: ((->) a b)
* les Fletxes: (Arrow p => p a b) (vegeu secció d'efectes fletxa)
Els profunctors poden ser base per a les Lents.

## Efectes

Un efecte és un possible canvi (d'estat, de l'entorn, una excepció, una fallada de càlcul (resultat no definit)), amb la possible producció d'un, diversos o bé cap resultat, que recomani seqüenciar les operacions que en depenguin per aconseguir la constància del resultat per a les mateixes entrades.
Es representa amb un tipus parametritzat pel tipus del resultat, com ara (IO tipusDelResultat).
* efecte simple: quan sempre hi ha resultat (representable amb (Efecte a)).
* efecte fallada: quan no sempre s'obté resultat (Les mònades amb element absorbent per l'esquerra en (>>=) en faciliten l'ús, per ex.: un tipus opcional: (Maybe a)). Vegeu Mònades amb efecte fallada. La implementació de l'element absorbent per l'esquerra en (>>=) fa innecessari la comprovació de la correctesa a cada encadenament.
* efecte múltiple amb possible fallada: diversos resultats o bé cap. Vegeu la classe MonadPlus, que permet la composició de resultats amb un Monoide.
Exemples:
* IO a : efectes superficials (ent/sortida, vars. globals, excepcions) amb resultat de tipus 'a'
* ST s a : encapsulament d'actualitzacions destructives (vars. locals amb cicle de vida limitat a l'àmbit i avaluació del càlcul)
       (La variable s representa l'espai d'avaluació de l'efecte)
* Maybe a : efecte fallada, resultat opcional de funcions parcialment definides.
* Either err a: efecte fallada amb info. de l'error, resultat de l'avaluació de codi de resultat incert. (try acció_que_pot_disparar_excepcions)

### Composició d'efectes - Combinació o bé encadenament de resultats

* La classe Applicative possibilita combinar els resultats de diverses accions amb una funció combinadora elevada al tipus de l'efecte. Defineix la composició d'un efecte amb resultat funció amb un efecte subseqüent sobre quin resultat s'aplicarà la funció resultant de l'efecte precedent. Com que en aplicar una funció de N paràmetres sobre un valor s'obté una funció de (N-1), podrem combinar els resultats d'una seqüència de N efectes amb un efecte que tingui per resultat una funció de N paràmetres o bé un constructor de N components. Vegeu Functor aplicatiu
* La classe Mònada possibilita la composició d'efectes mitjançant l'encadenament (>>=) combinant un efecte amb una funció d'efectes sobre el resultat de l'efecte precedent. Vegeu Mònada (programació funcional)
* La classe Arrow (cat:Fletxa) generalitza les mònades prenent les funcions amb efecte de la mònada, fixant-ne el tipus de l'entrada, modelant la seqüència d'efectes com un encadenament de funcions d'efectes col·laterals. Per poder efectuar càlculs amb els resultats en una seqüència d'efectes, caldrà aparellar el resultat precedent amb l'actual, i utilitzar el tractament de parells que les fletxes inclouen. Vegeu Fletxa (programació funcional)
El model Applicative no seqüència les computacions sinó només la seva engegada i per això s'utilitza en la combinació de processos paral·lels, mentre que en els altres models el resultat de la computació precedent s'ofereix de paràmetre de la següent.

#### Efectes aplicatius

Efectes que implementen la classe Applicative.

##### Generació d'efectes aplicatius

* A la classe Applicative (mòdul Control.Applicative) "pure" eleva un valor (funcions incloses) a la categoria d'efecte aplicatiu (que implementa Applicative).

##### Combinació de resultats d'efectes aplicatius

* La classe Applicative facilita la combinació dels resultats d'una seqüència d'efectes amb un combinador (funció, o bé un constructor), elevat a la categoria d'efecte. És com aplicar la funció o constructor elevats a efecte, als resultats dels efectes com a paràmetres.
   * El generador pure servirà per elevar el combinador (funció o bé constructor) a la categoria d'efecte.
   * La funció fmap si s'aplica a un combinador de diversos paràmetres sobre un efecte, retorna un efecte funció aplicable sobre la resta de paràmetres.
   * Applicative no pressuposa la seqüenciació dels efectes col·laterals sinó només la seva engegada, doncs els efectes poden executar-se en paral·lel i esperar que acabin per combinar-ne els resultats, com ara el cas de l'efecte aplicatiu Concurrently que combina resultats d'accions executades en paral·lel.
Exemple combinant amb el constructor de Tupla2:

#### Efectes monàdics

Efectes que implementen la classe Monad.

##### Generació d'efectes monàdics

* A la classe Mònada (mòdul Control.Monad) "return" eleva un valor a la categoria d'efecte monàdic (que implementa Monad).
Actualment la classe Applicative és base per a la classe Monad, i return = pure, i (>>) = (*>)

##### Seqüenciació d'efectes monàdics

* A la classe Mònada (mòdul Control.Monad) (>>=) encadena un efecte amb una funció efecte sobre el resultat de l'efecte precedent.
Actualment la classe Applicative és base per a la classe Monad i els operadors corresp. ofereixen la mateixa operatòria(>>) = (*>)
Les funcions del mòdul Control.Monad (forM_ llista acció, forever acció, replicateM_ n acció) fan la feina de les clàusules de control imperatiu d'altres llenguatges (forEach, while true do ..., for i = 1 to n do ...).
Vegeu també Combinadors aplicatius partint de mònades

#### Efectes fletxa

Vegeu ref.
Una fletxa, concepte desenvolupat per John Hughes, és una generalització d'una funció on el resultat pot dependre d'efectes col·laterals o bé ser independent de l'entrada. Es concreta en les classes Category (que generalitza les funcions amb paràmetres pel tipus de l'entrada i de la sortida) i la seva especialització Arrow que refina les categories amb el tractament de parells, necessari per combinar-ne resultats. Vegeu Fletxa (programació funcional)#Fletxes i Parells

##### Generació d'efectes fletxa

* A la classe Arrow (mòdul Control.Arrow) "arr" eleva una funció a la categoria d'efecte fletxa (computacions amb tractament de parells).
Les fletxes generalitzen les mònades. Podem convertir qualsevol funció d'efectes monàdics (a -> efecte b) en una Fletxa de Kleisli, prefixant-la amb el constructor Kleisli.
A ghci:

##### Seqüenciació d'efectes fletxa

* La classe Category (mòdul Control.Category) generalitza els morfismes, la classe Arrow especialitza les categories amb el tractament de parells, necessari per les computacions amb fletxes. Les funcions també implementen les categories.
Encadenament de computacions:
La composició de fletxes ha de mantenir l'operació generadora (arr) i el tractament de parells.
Exemples: Ent./Sort. amb fletxes de Kleisli (mònades elevades a fletxes) i el tractament de XML amb fletxes sobre subarbres XML.
Compiladors que suporten Fletxes: GHC, Hugs

### Entrada / Sortida - Mònades

Les operacions d'entrada/sortida produeixen efectes a l'entorn i un resultat programàtic opcional en forma de valor (cas d'entrada), es representa amb el tipus (IO a). En cas de sortida, es retorna el valor buit, resultant el tipus (IO).
Per la seqüenciació d'operacions s'utilitza preferentment la classe mònada sobre el tipus (IO a), donant lloc a la mònada IO.
La funció inicial main de qualsevol programa ha de ser una expressió d'operacions d'ent./sortida i, per tant, del tipus de la mònada IO.
La funció evaluate permet seqüenciar com a efecte IO, les excepcions que pot llançar una expressió funcional pura.
Les accions de lectura/escriptura de variables globals IORef també formen part dels efectes IO.

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

Encadenament de les instruccions d'un bloc. Vegeu mònada - Blocs Do
La clàusula do exposa l'encadenament d'efectes de manera seqüencial, amb una expressió monàdica per línia, introduint l'estil imperatiu.
correspondència :
| sintaxi | mònada | expressió equivalent | comentari |
| patró <- acció; e | Mònada amb mètode fail per si falla l'encaix | let { f patró = e ; f _ = fail "error ..." } in acció >>= f | mònada Monad a GHC < 8.8 o bé mònada MonadFail a GHC >= 8.0 |
| patró <- acció; e | Mònada sense mètode fail. L'encaix haurà de ser irrefutable | acció >>= (\ patró -> e) | mònada Monad des de GHC >= 8.8 |
| acció; e | | acció >> e | |
| let {x = v1; y = v2} ; e | | let {x = v1; y = v2} in e | el bloc del let es pot expressar amb sagnat aliniant el sagnat a la primera variable |
Vegeu també Recursivitat en les definicions als subblocs let, i també, recursivitat en els efectes en subblocs rec

##### Seqüències i efectes - la classe Traversable

Permet l'avaluació seqüencial dels elements d'una col·lecció travessable d'esquerra a dreta si són efectes o bé de les imatges del mapeig dels elements amb una funció d'efectes (a -> efecte b). Vegeu el mòdul Data.Traversable.
* Traversable i efectes aplicatius (que implementen Applicative)
* Traversable i efectes monàdics (que implementen Monad)
* Des de GHC 8.2 la classe Bitraversable ofereix una operativa similar per a col·leccions d'elements de domini dual, per ex. (Either a b)
* forM equival a mapM amb els paràmetres intercanviats.
* hi ha versions amb un guió baix al final per quan només interessa l'efecte col·lateral descartant els resultats (resultat buit com a (IO)). forM_ equival al forEach d'altres llenguatges.
* Bloc do com a paràmetre:
El bloc do no és més que un artifici sintàctic per escriure una expressió de tipus mònada, una acció formada per l'encadenament d'accions amb funcions d'efectes sobre el resultat de l'acció precedent. Com a tal expressió es pot posar com a paràmetre.
Aquí el posem com a paràmetre (operand de '$') d'un llaç (Monad.forever) amb control d'excepcions.
($) és una funció amb polimorfisme de rang 1 (Vegeu rank-n polymorphism), i no admet funcions polimòrfiques com a paràmetre.

##### Alternatives en efectes - Blocs do niuats

Per posar més d'una instrucció en una branca d'un "case" o d'un "if" cal agrupar-les dins un subbloc "do"
Les funcions when i unless de Control.Monad proporcionen l'avaluació condicionada d'un efecte.

##### Recursivitat en els blocs do

Vegeu Mònada (programació funcional)#Recursivitat en els blocs do

### excepcions

1. Les excepcions del mòdul Control.Exception de la biblioteca base són un efecte global IO. Poden ser llançades des de codi funcional, però només poden ésser caçades en una expressió o bloc do de la mònada IO Aquesta limitació es pot superar si fem servir la biblioteca exceptions descrita a continuació.
2. La biblioteca exceptions suporta tractament d'excepcions genèric respecte al tipus de la mònada, i és extensible a les mònades transformades. A més inclou els tipus d'excepció genèric SomeException de la biblioteca base. Les IOError (IOExceptions) són admeses en el context de la mònada IO que implementa les classes definides. També inclou un transformador per al tractament encapsulable en codi funcional pur.
3. La biblio safe-exceptions permet tractar adequadament de manera diferenciada les excepcions síncrones i les asíncrones (les llançades des d'altres fils d'execució al propi) sense perdre'n cap pel camí.
Habitualment les expressions funcionals s'avaluen de manera tardana en el moment que se'n demana el valor. Per assegurar-ne la caça i tractament d'excepcions en un punt, la funció evaluate de Control.Exception permet forçar-ne el càlcul dins el codi seqüencial (monàdic) fent aflorar les possibles excepcions en un punt de la seqüència. Si l'expressió conté tipus algebraics, cal tenir en compte que els constructors poden aturar l'avaluació de les expressions dels components si aquests no estan definits com a estrictes (prefix '!'). Per avaluar-los completament en aquest cas, caldrà avaluar en profunditat a Forma Normal, fent servir force de DeepSeq com a (evaluate. force $ expr).
Segons l'apartat Catching exceptions del mòdul Control.Exception.
* Per fer neteja en recuperar-se d'una excepció, es recomana bracket o bé finally o bé onException
* Per recuperar-se d'una excepció i fer alguna cosa més, es recomana try
* Per caçar excepcions asíncrones (les llançades des d'un altre fil d'execució) es recomana catch o bé catches.
Vegeu també "Exceptions Best Practices in Haskell".

#### Generadors d'excepcions

* userError: generador d'excepcions d'usuari del Haskell98.
* la nova classe Exception permet generar excepcions de tipus definits per l'usuari. Requereix que el tipus implementi Show i Typeable.

#### Llançadors

Vegeu errors I/O.

##### Llançador generalitzat

* el paquet exceptions generalitza el context de les excepcions. Permet llançar i caçar excepcions des de mònades diferents de l'IO. (aquelles que implementin MonadThrow i MonadCatch).

#### excepcions en la gestió de recursos
##### bracket

Enclou en tres paràmetres la vetlla d'excepcions en un càlcul amb un recurs, i els manipuladors per adquirir-lo i per alliberar-lo en cas d'excepció o en acabar.
   * el recurs obert a l'acció del primer paràmetre es passa als paràmetres següents.
Exemple:

###### bracket i avaluació tardana

Un error comú amb l'Ent./Sortida tardana és el següent:
A l'exemple següent hGetContents no s'avalua fins que no s'avaluï el withFile, però com que no entrega el contingut si no li ho demanen, bracket (withFile és aplicació parcial de bracket) tanca el recurs. El resultat és la sortida buida. El compilador no avisa de l'error !!
La versió correcta és ficar el consumidor dins l'acció vetllada pel bracket, és a dir, el bloc del withFile, consumint el contingut abans no es tanqui el recurs.

#### try - avaluació i anàlisi per casos de les expressions llançadores d'excepcions

try avalua un efecte IO que pot llançar excepcions retornant èxit o fallada en un tipus Either permetent-ne l'anàlisi per casos. (Either tipError) implementa una mònada amb efecte fallada. (Left error) és l'element absorbent per l'esquerra de Either en (>>=). Això permet encadenar amb (>>=) diversos efectes que poden fallar obtenint l'error del primer que falla.
Amb TipDada == Micro (Coma fixa) l'excepció salta
Amb TipDada == Double (Coma flotant IEEE 754), no hi ha excepció (Divisió entre zero), dona:
try també es pot fer servir amb finally, però bracket és més adequat per la gestió de recursos.

##### try generalitzat

Del paquet exceptions, generalitzant el context de llançament i caça d'excepcions per a mònades diferents de l'IO (aquelles que implementin MonadCatch)

##### finally

Assegura l'exec. de la segona acció malgrat excepcions en la primera. Si hi ha hagut excepció, és rellançada al final.

###### onException

    com finally però només executa el segon bloc en cas que hi hagi hagut excepció.

#### catch -- per caçar excepcions (especialment les asíncrones)

La clàusula catch té dos paràmetres, l'operació vetllada i el manipulador d'excepcions Les excepcions del Haskell98 (tipus algebraic Exception) a GHC van passar al mòdul Control.OldException però ha sigut retirat a la versió 7.6.1
Per a les excepcions noves de GHC (qualsevol tipus que implementi la classe Exception), són al mòdul Control.Exception
* Gestors d'excepció segons el tipus. Requereix l'extensió de llenguatge ScopedTypeVariables.
* el model d'aplicació successiva de catchs per tractar els diferents tipus d'excepcions té una pega: les excepcions llançades dins dels handlers poden ser caçades pels catchs subseqüents
   * la funció catches posposa el tractament de les excepcions produïdes dins els handlers.
Vegeu catches.
Vegeu exemple Compilador Haskell de Glasgow#Excepcions de tipus definits per l'usuari.

##### catch generalitzat

* el paquet exceptions generalitza el context de les excepcions. Permet llançar i caçar excepcions des de mònades diferents de l'IO (aquelles que implementin MonadCatch).
* el paquet safe-exceptions permet separar el tractament de les excepcions síncrones i asíncrones (les originades des d'altres fils d'execució) millorant la seguretat del tractament.

#### La funció error assenyala la fallada del programa

Per al cas d'estats inconsistents o bé operacions no definides per als valors dels paràmetres.
La crida a la rutina error dispara una excepció genèrica ErrorCall que mostra el missatge.
És preferible evitar-ne l'ús en funcions parcials, convertint-les en totals amb resultat opcional i analitzar-ne el resultat dins la rutina que ha fet la crida amb paràmetres il·legals.
* des de GHC 7.8.1: errorWithStackTrace amb bolcat de pìla si s'ha compilat per l'ajustatge amb profiling.
    No requereix l'opció d'execució de depuració +RTS -xc però sí ghc -prof -fprof-auto Main.hs;
    L'ús de la versió d'ajustatge (profiling) del RunTimeSystem requereix disposar de versions compilades amb profiling de totes les dependències.
Això millora a partir de la versió 7.10.2 amb un nou mecanisme d'obtenció d'una pila de crides mitjançant paràmetres implícits especials inclosos al context de les crides que es pretén traçar, sense haver de recórrer al profiling.
A GHC 8.0 error incorpora la funcionalitat de errorWithStackTrace mostrant la situació de l'error. Excepte al paquet base, on les crides a error han estat reanomenades a errorWithoutStackTrace.
Fins ara era millor reconvertir les funcions parcials en funcions totals amb resultat opcional (Maybe) analitzant el resultat a la funció que fa la crida, i en cas de resultat inesperat provocar la petada,
* o bé amb encaix incomplet obtenint la posició de la petada,
* o bé amb la crida err equivalent a error del paquet file-location que ens permet mostrar la posició (requereix l'extensió TemplateHaskell). $(x) és un mecanisme de GHC per avaluar en temps de compilació, anomenat crida splice.
Resultat:
La biblioteca Safe ofereix diverses alternatives de les funcions del Prelude que poden petar.
Ara per ara, per assegurar la finalització del programa, és millor evitar les funcions parcials que criden a error i compilar amb -Wall per assegurar l'exhaustivitat dels encaixos.
Cal tenir en compte que els accessors de registres amb més d'un constructor que no siguin comuns a tots ells, també són funcions parcials.

#### Assercions, Precondicions i Postcondicions

assert avalua la condició, i si és certa retorna el segon argument i,si no, peta dient-nos on.
L'ús de l'opció d'optimització (-O ó bé -On | n>0) elimina les assercions del codi objecte.
per exemple:
* Amb resultat opcional per evitar petades per crides a 'error'
* Amb excepcions:

##### obtenció del punt de crida origen de la violació de la precondició

1. Amb paràmetre implícit especial de tipus CallStack
Vegeu ref. (Des de GHC 7.10.2) La seva obtenció reflecteix la pila d'aquelles crides on explícitament aparegui l'implícit de tipus CallStack com a restricció de context, amb el mateix nom de variable.
Des de GHC 8.0 vindrà definit un sinònim de restricció HasCallStack que evitarà la necessitat de l'extensió de sintaxi ImplicitParams.
Exemple:
2. Alternativa. Bolcar la pila de crides simulada, havent compilat amb la variant d'ajustatge del RunTimeSystem. (profiling)
La comprovació de la precondició dins la rutina no ens informarà de la rutina origen del problema, excepte si habilitem la simulació de pila de crides de l'ajustatge (compilant amb -prof i executant amb +RTS -xc). Vegeu Depuració. El problema de la manca d'informació de situació en les petades

#### No finalització - Símbol ⊥ (Bottom)

Valor intern que atura el programa prematurament indicant "No finalització del programa", especialment com a opció de fons en un case, en cas que no encaixi cap de les opcions o bé un bucle sens fi. El tipus de ⊥ és arbitrari.
En anglès bottom com a verb vol dir "tocar fons". En català es podria anomenar "fondeig" (fondejar: immobilitzar una barca, ancorant-la al fons).

##### Implementació pendent - Undefined

undefined és un valor de fondeig (⊥: atura el programa) per poder explicitar el tipus d'una funció pendent d'implementar i poder així passar la compilació. Crida a la funció error.

### Canvis d'estat - Variables

Haskell permet crear objectes mudables, que poden canviar d'estat mitjançant operacions sempre dins d'una mònada (sinó l'ordre i, per tant, el resultat, no estarien garantits).
La mònada IO caracteritza l'estat global de l'aplicació amb objectes amb cicle de vida no acotat. Les variables mudables globals són les IORef's.
La mònada ST caracteritza l'estat local d'una computació puntual, permetent encapsular actualitzacions in situ (destructives) dins de codi funcional pur. Les variables mudables locals són les STRef's i el seu cicle de vida queda limitat a l'àmbit de l'efecte ST.
Caldrà distingir el tipus de la mònada especificant el tipus resultant de l'expressió o bloc do.
La sincronització d'accés a variables des de diferents fils d'execució (detallat a Haskell concurrent) es pot obtenir:
* amb sincronització per baldes (ang:locks) amb variables MVar's (ang:mutable variable o més precisament mailbox variable).
* amb les transaccions en memòria (similars a les de bases de dades). La mònada STM (inicials de Software Transactional Memory) modela el funcionament i validació de les transaccions. Les variables transaccionals són les TVar (immutables) i TMVar (mudables).
variables :
| tipus | mònada | generadors | mòdul | descripció |
| IORef a | IO | newIORef x | Data.IORef | vars. globals no sincronitzades, cicle de vida no acotat |
| STRef a | ST | newSTRef x | Data.STRef | vars. per a canvis d'estat encapsulables, cicle de vida lligat a l'àmbit de ST |
| MVar a | IO | newMVar x -- var buida per a un tipus T newEmptyMVar:: IO (MVar T) | Control.Concurrent.MVar | bústia de comunicació d'un sol element emprada com a variable sincronitzada amb Monitor (concurrència) també es pot fer servir com a semàfor binari. |
| TVar a | STM IO | newTVar x -- encapsulable newTVarIO x -- global | Control.Concurrent.STM.TVar | posicions de memòria compartida suporten transaccions de memòria atòmiques |
| TMVar a | STM IO | newTMVar x -- encapsulable newTMVarIO x -- global | Control.Concurrent.STM.TMVar | MVar protegida per transaccions de memòria |

#### Variables d'estat global no sincronitzades IORef

Les referències IORef, equivalents de les ref del ML Estàndard, permeten modificar l'estat global caracteritzat com a efecte IO.
No és convenient utilitzar una mateixa IORef en diferents fils d'execució. Protegir-ne més d'una mitjançant atomicModifyIORef està desaconsellat (les MVar hi són més indicades).

#### Variables d'àmbit local STRef per l'encapsulament d'efectes col·laterals

La mònada ST (abbrev. de State) encapsula canvis d'estat dins de codi funcional pur i permet fer computacions amb actualitzacions in situ (destructives) mitjançant referències STRef a objectes de cicle de vida restringit a l'àmbit i avaluació de l'efecte.

##### en memòria local

* Els efectes locals produïts en un fil d'execució (ST s tipusDelResultat), venen parametritzats amb una variable s (l'espai d'avaluació de l'efecte), que es deixa lliure per indicar l'espai propi del fil d'execució.
* la funció runST avalua un efecte local i n'extreu el resultat.

##### en memòria global

* stToIO avalua un efecte local de tipus (ST s tipusDelResultat) en l'espai de memòria global, assignant RealWorld a la variable s, oferint el resultat en la mònada IO.

#### Variables MVar per a l'accés sincronitzat

Les variables MVar ofereixen l'accés sincronitzat entre fils d'execució amb el mecanisme de les bústies de comunicació. Ampliació a Haskell concurrent

#### Mutabilitat als vectors

Vegeu vectors d'elements d'allotjament directe

### Entrada/Sortida reactiva - Els Iterats (ang:Iteratees)

L'abstracció dels Iterats aporta un altre enfocament, descomponent l'entrada/sortida en productors del corrent de dades, consumidors i transformadors.
* Els Iterats (consumidors) es descriuen com una abstracció componible per al procés incremental d'una seqüència de parts de l'entrada de dades, per l'obtenció d'un resultat. És un component reactiu. Es reacciona a l'entrada de cadascun dels elements (o bé troç de fitxer (ang:chunk)) com si fos un plegat (reducció), combinant l'element (o bé el troç de fitxer) en funció de l'estat, que s'actualitza en funció de l'entrada, i en rebre el "fi de seqüència" s'ofereix el resultat.
* L'Enumerador (productor) és l'abstracció que genera el corrent de dades per al consum dels Iterats.
* Els Enumerats (ang: Enumeratee) actuen com a consumidors i productors alhora, fent de transformadors interposats.
El procés es completa en associar un productor (l'Enumerador) amb un o més components reactius (l'Iterat amb possible interposició dels Enumerats)

#### Nota el sufix -ee

       En anglès, donat un verb afegint-li el sufix -er tenim un nom subjecte d'una acció com ara del verb employ el substantiu Employer.
       El sufix -ee obté de l'acció un subjecte passiu (persona/objecte afectats o subordinats), així el parell (Employer, Employee) es podria traduir per (Contractador, Contractat)
       Així els termes tècnics {Iteratee, Enumeratee} en català serien {l'Iterat, l'Enumerat} com Refugee és {el refugiat}.
Algunes implementacions inclouen una capa de gestió de recursos (ex. el transformador de mònades ResourceT als conduits) que en ésser cridat (runResourceT), executa les accions incrementals i, en acabar, les accions d'alliberament registrades pel generador.

### Efecte fallada en una seqüència de computacions

Els elements absorbents per l'esquerra de l'encadenament en una mònada, en produir un resultat absorbent assimilable a fallada, fan inútil l'avaluació de la computació subseqüent, perquè el resultat és el mateix valor, de manera que l'encadenament progressa només per als elements no absorbents en (>>=).
Per exemple:
* a la mònada Maybe: l'encadenament de resultats opcionals de funcions definides parcialment (f x >>= g), s'atura a la primera fallada
* a la mònada Either: l'encadenament d'avaluacions d'accions que disparen excepcions (try acció1 >>= \_ -> try acció2), s'atura al primer Left
Això facilita l'encadenament de computacions que poden fallar, sense haver de consultar la correcció del resultat a cada pas.
| tipus de la mònada | element absorbent en (>>=) |
| Maybe a | Nothing |
| Either err a | Left err |
| classe | |
| MonadPlus m | mzero |

#### fallada monàdica en el codi funcional

Com acabem d'esmentar, l'element absorbent en l'encadenament en la mònada Maybe (o bé Either) evita l'avaluació de les computacions posteriors.
prova:

##### un tipus específic per al subdomini de casos definits

I una funció de validació dels casos definits:

#### fallada monàdica en els efectes col·laterals - el transformadors EitherT i MaybeT

La fallada en la mònada IO per encaixos incomplets del segon operand de (>>=) (op. fail desplaçada (des de GHC 8.0) a la classe MonadFail) es produeix disparant una excepció IOError.
En el cas de la mònada ST, el comportament no està definit. La implementació per defecte crida la rutina error aturant el programa.
Per afegir-hi la funcionalitat de l'element absorbent en (>>=) cal aplicar-hi un transformador de mònades que la incorpori.
El transformador de mònades EitherT, de manera similar al MaybeT, afegeix la possibilitat d'evitar càlculs posteriors a la fallada, a una mònada, afegint-hi a més a més, informació de l'error. Aquí l'aplicarem a la mònada IO, resultant la mònada (EitherT tipError IO).

## Lents (Referències funcionals) - Consulta i manipulació de parts d'estructures complexes

Una lent és un mecanisme componible per enfocar una part d'una estructura per la consulta, o bé per la modificació de l'estructura alterant-ne el component enfocat.
També s'anomenen referències funcionals, per ésser l'equivalent funcional dels punters als components de l'Orientació a objectes.
Classes de lents:
* lents pròpiament dites: permeten adreçar components d'un tipus producte, per exemple un tipus de registre
* prismes: permeten adreçar components d'un tipus suma (unió discriminada), on la selecció del component pot fallar si el valor no correspon a la variant pretesa.
* isos: permeten adreçar components sobre una transformació reversible, per exemple d'una tupla2 (a, b) transformada en (b, a)
* travesses i plegats: permeten adreçar múltiples components per una transformació dels mateixos o bé una reducció dels valors mitjançant un plegament.
* Història de les lents.
* Lents de Van Laarhoven. Va ser el creador de la base teòrica de les lents actual emprada per la biblioteca "lens" de Edward Kmett.
* Lents basades en Profunctors. Recentment s'ha comprovat que els profunctors descrits més amunt ofereixen una manera més planera de definir-hi les lents.
Exemple amb biblioteca "lens" (lents de Van Laarhoven) a Compilador Haskell de Glasgow#Lents de Van Laarhoven -- Consulta i manipulació de parts d'estructures complexes

### Lents basades en profunctors

* la biblioteca Mezzolens defineix les lents com una funció de transformadors: una transformació (profunctor) d'estructures en funció de la transformació d'un component.
Per fabricar una lent caldrà una funció de selecció del component enfocat i una funció de transformació de l'estructura en funció de la imatge (transformada) del component enfocat.
Són instàncies de Profunctor les funcions i les fletxes de Kleisli.
Per exemple podem aplicar una lent a un profunctor funció que transformi el component, obtenint un profunctor del mateix tipus (funció) que transforma l'estructura que el conté.
La composició de lents (composició de funcions de profunctors) ens permetrà manipular components inserits profundament.
Strong és una especialitat de Profunctor. Els seus mètodes poden passar com a lents que proporcionen una transformació de l'estructura Parell mitjançant la transformació d'un component amb el profunctor d'entrada. (vegeu Mezzolens.Profunctor)
així, aplicant les lents precedents a una funció que transformi el component obtenim una funció sobre el parell que el conté:
Generació de lents (amb "lens getter setter" de Mezzolens.Unchecked)
* el getter selecciona de l'estructura el component que interessa (ta -> a).
* el setter proporciona la transformació de l'estructura continent en funció de la imatge del component enfocat (b -> ta -> tb).
* el resultat és una lent que ofereix una transformació de les estructures ta a tb, en funció d'una transformació del component de a a b (p a b -> p ta tb).
Treballarem amb lents simples, que no modifiquen el tipus
Exemple:

#### Prisma

Un prisma és una lent per enfocar un component d'un tipus suma (pluri-constructor), que pot no ser present en un valor i, per tant, fallar.
La funció de selecció, primer paràmetre del generador prism, ofereix en un tipus Either el component enfocat o bé, cas que la variant del tipus suma no sigui la desitjada, un valor del tipus de l'estructura transformada resultant que signifiqui la fallada (ta -> Either tb a).
El segon paràmetre del generador prism construeix l'estructura resultant partint de la imatge del component enfocat (b -> tb).
Exemple amb el cap en una llista.

#### Travesses i plegats amb lents

La classe Wandering ofereix una lent per enfocar tots els elements d'un contenidor travessable.
* el mètode wander del profunctor Wandering ofereix una lent per travessar un travessable. Caldrà compondre'l amb la lent sobre l'element.
* la funció Mezzolens.gets fa servir Data.Functor.Constant.Constant com a Applicative, que ignora les funcions de composició i retorna la composició Monoidal dels elements.
* toListOf obté una seqüència de resultats, a base d'elevar-los amb pure a un Applicative Monoide que cal concretar amb una restricció de tipus.
* sumOf obté el plegat sobre el Monoide del newtype Sum.

## Mòduls

Per compilar no cal especificar tots els mòduls a la comanda sinó només el fitxer del mòdul que conté la clàusula main.
Els mòduls a importar s'interpreten com a noms de fitxer sense l'extensió (l'extensió del fitxer pot indicar un tipus de document del qual s'obtindrà el codi Haskell mitjançant un preprocessador), els compostos per parts separades per un punt com a camí CarpetaA.CarpetaB.NomDelFitxer.
* (.hs): mòdul en codi Haskell
* (.lhs): mòdul de Haskell literari.
* (.x): mòdul d'especificació de lèxic segons preprocessador Alex.
* (.y): mòdul d'especificació de gramàtica segons preprocessador Happy.

### encapsulament

No hi ha doble especificació (interfície / implementació) per als mòduls. S'exporten els identificadors llistats a la clàusula module, o tots si no hi ha llista.

#### distingir entre tipus i valors a l'export./import. quan hi ha coincidències

Per exportar operadors constructors de tipus i no confondre'ls amb un operador funció del mateix nom, cal prefixar-lo amb el prefix type que explicita l'espai de noms al qual pertany l'identificador que volem exportar o bé importar. Cal esmentar l'extensió de llenguatge ExplicitNamespaces o altres que la impliquin.

#### accés públic als membres de classes i tipus

Per
* exportar els identificadors interns d'un tipus: constructors; noms de camp en registres.
* i facilitar l'accés públic als mètodes d'una classe,
cal esmentar-los entre parèntesis a l'exportació, o bé adjuntar l'el·lipsi (..) per indicar tots. Altrament el tipus o la classe seran opacs.

#### Importació
##### Importació d'instàncies (implementacions de classes)

* les instàncies visibles d'un mòdul s'exporten sempre; qualsevol importació del mòdul les importa totes.

##### Importacions especificant el paquet desitjat

Cal esmentar la pragma d'ampliació de sintaxi {-# LANGUAGE PackageImports #-}

##### Evitar la importació automàtica de les funcions predefinides

Per evitar-ne la importació de només algunes:
Amb la pragma {-# LANGUAGE NoImplicitPrelude #-} amaguem tot el Prelude, i podem substituir-lo per un altre mòdul:
ús:

#### espai de noms de mòdul jeràrquic

Els detalls de tractament intern que no formaran part de l'API se solen encapsular en mòduls allotjats en carpetes internes. Per accedir-hi, un nom del mòdul separat per punts ("A.B.NomDelFitxer") reflecteix el camí d'accés (A/B/NomDelFitxer), excepte l'extensió del fitxer, que indica si el font és de codi (.hs) o és un document al qual cal aplicar un preprocessador (de lèxic (.x), de gramàtica (.y), de programació literària (incrustada dins la documentació) (.lhs), o altres) per obtenir-ne el codi font.
En compilar, el senyal -i<dirs> indica a GHC la llista de directoris base de la recerca dels fonts
És corrent reanomenar els noms jeràrquics a un sobrenom curt

#### mòduls amb referències mútues (mútuament recursius)

Vegeu-ho a Compilador Haskell de Glasgow#Mòduls amb referències mútues (mútuament recursius)

#### arrencada

El mòdul principal ha de dur per nom de mòdul "Main" i ha d'exportar la funció "main". Si no hi ha clàusula module es pren per defecte "module Main where", exportant tots els identificadors (útil per a proves a l'intèrpret).
Els arguments de la línia d'ordres de consola (getArgs), no inclouen el nom del programa, que s'obté amb getProgName.
Per indicar l'eixida amb codi de finalització: exitWith (ExitSuccess | ExitFailure codi_de_finalització) dispara una excepció de fi de programa.
Exemple senzill. (System.Environment no té en compte la codif. local, vegeu comentari):
En el llançament, a més dels paràmetres del programa, s'hi poden afegir paràmetres per al Run Time System a partir del separador +RTS tancant opcionalment amb -RTS en cas d'haver d'afegir, tot seguit, paràmetres pel programa

##### arrencada amb opcions

Vegeu-ho a GHC.

#### funcions i tipus predefinits i biblioteques bàsiques

El mòdul de funcions predefinides es coneix com a "Prelude". Vegeu Prelude estàndard. Prelude del GHC.
Les API's de les biblioteques bàsiques són aquí
Podeu consultar a quins mòduls pot pertànyer un identificador mitjançant els cercadors de l'API del Haskell Arxivat 2010-03-22 a Wayback Machine. Hayoo o bé Hoogle

#### Precisió dels tipus bàsics

Vegeu-ho a GHC#Precisió dels tipus bàsics

## Vectors
### Vectors per interfície
   #### Vectors immutables

       interfície (classe) IArray, parametritzats pels tipus de l'índex i de l'element. Vegeu #Vectors immutables del H98

   #### Vectors mudables

       interfície (classe) MArray, parametritzats pels tipus de l'índex i de l'element. Exemple a #Vectors mudables de dades no encapsulades

   #### Vectors d'alt rendiment

       al paquet vector, vectors d'índex enter amb base 0, immutables (tipus Vector) i mudables (tipus MVector), amb versions per a elements allotjats indirectament (allotjament encapsulat) o bé amb allotjament directe (qualificats Unboxed). Paquets relacionats: vector-algorithms (algorismes eficients en espai amb actualitzacions in-situ per a vectors mudables), vector-instances, vector-binary-instances (instàncies de serialització), vector-read-instances, ...

   #### Vectors pluridimensionals (amb paral·lelisme intern)

       a GHC amb el paquet REPA (Regular Parallel Arrays)

   #### Vectors de tractament paral·lel (paral·lelisme de dades DPH)

       interfície PArray. (cada op. conclou havent avaluat tots els elements) Només a GHC.

   #### Vectors amb allotjament contigu, per a ésser accedits des de mòduls forans (per ex. lleng. C)

       interfície Storable.

#### Immutables, per implementació i allotjament dels elements

Els elements dels vectors poden estar:
* allotjats indirectament (encapsulats en memòria dinàmica, ang:boxed): representats per un punter (l'avaluació serà tardana)
* allotjats directament (no encapsulats, ang:unboxed): representats per un valor, evidentment avaluats abans d'ésser-hi assignats (avaluació estricta, el nom del tipus es diferencia incorporant la lletra 'U' de Unboxed com a xxUArray).

##### amb actualització de còpia completa

Ineficients en espai. Vegeu Array UArray

##### amb actualització per aplicació de diferències. DiffArrays

* Vegeu DiffArrays. s'afavoreix l'accés en temps constant a la versió més recent; els valors de referències antigues s'obtenen per aplicació de les diferències i, per tant, l'accés és més lent com més antiga sigui la variable, és a dir, més actualitzacions funcionals hagi sofert.

#### Mudables, per implementació i allotjament

* Vectors d'accés aleatori com a efecte global IO (objectes amb cicle de vida no acotat), en memòria global.
* Vectors d'accés aleatori com a efecte encapsulable ST (objectes amb vida lligada a l'àmbit de l'efecte), en memòria local (o bé global cas d'avaluació de l'efecte ST amb stToIO).
(El paràm. 's' correspon al param. de l'espai de l'efecte local (ST s tipResultat))
Exemples a #Vectors mudables de dades no encapsulades.

#### Vectors immutables del H98

La classe Array combinada amb la Ix (índexs), especificades en el Haskell98, implementen vectors immutables amb elements d'avaluació tardana.

##### vector amb índex de tipus enumerat

Caldrà que l'enumerat implementi la classe dels índexs Ix (A GHC: al mòdul Data.Ix)
Exemple:
A part d'aquests vectors, que generen una còpia a cada actualització, n'hi ha d'altres de força més eficients. Entre aquests vegeu més avall #Vectors mudables de dades no encapsulades.

#### Vectors mudables de dades no encapsulades

Amb allotjament directe (no encapsulat) dels elements.

##### vect. mudables amb cicle de vida lligat a l'àmbit (efecte encapsulable ST)

* Per a vectors amb cicle de vida lligat a l'àmbit i tipus del vector: (STUArray s tipus_de_l'índex tipus_de_l'element). (La 'U' és per Unboxed: allotja el valor i no un punter)
    el tipus de l'índex ha d'implementar la classe Ix igual que els vectors de la def. del 98.

##### vect. mudables amb cicle de vida no acotat (efecte superficial IO)

* En memòria global i tipus del vector: (IOUArray tipus_de_l'índex tipus_de_l'element)

## Genèrics

L'equivalent dels mòduls genèrics (paramètrics en tipus) d'altres llenguatges, es pot fer de dues maneres:
* l'antiga, afegint tots els paràmetres de tipus als paràmetres de la classe de tipus, especificant les dependències funcionals.
* la moderna, els paràmetres de tipus independents s'afegeixen als de la classe i els dependents es defineixen com a tipus associats a la classe.

### Genèrics amb dependències funcionals

Afegint les variables de tipus com a paràmetres de les classes i definint-ne les relacions amb dependències funcionals.
A les classes multiparàmetre pot ser que una part dels paràmetres vingui determinada per altres (per exemple el tipus de la col·lecció determina el tipus de l'element).
La sintaxi de les dependències funcionals és:
indicant que a les instàncies el grup de valors (a, b) determina el de 'c' i n'ha d'esperar un sol valor per cada ocurrència del grup determinador. Els tipus determinats s'expressen en funció dels determinadors, i si són monomòrfics (sense variables) n'hi ha prou amb el comodí '_'.

### Genèrics amb tipus associats

Els paràmetres de tipus dependents del tipus índex de la classe s'especifiquen en funció del mateix. Són abstractes a la definició de la signatura i concretables a les instàncies.
Exemple:
* Una variant d'aquest sistema és definir els tipus associats no dins la classe sinó a nivell de mòdul, mitjançant #Famílies de tipus (clàusules type family/instance per als àlies de tipus, data family/instance per als tipus estructurals):

#### Correspondència amb els functors de ML

Correspondència de les classes de Haskell amb els functors de ML, en definir una signatura de conjunt i la seva implementació. Vegeu Functors a OCaml
correspondència aproximada :
| Haskell | ML | a l'exemple |
| class | signature | Conjunt |
| instance | structure | |
| class (amb requeriments de context) | signatura del functor | |
| instance paramètrica (amb requeriments de context) | def. del functor | ConjuntVectorAmbIgualtat |
| restricció a un tipus concret del tipus d'una instance paramètrica | aplicació del functor | ConjuntVectorDeSencers (els Int implementen igualtat) |
* Amb classes i tipus associats i canviant l'agregació de llista a vector.

## Temes avançats
### Monomorfisme, polimorfisme i quantificadors explícits

Vegeu ref.

#### Polimorfisme universal

El polimorfisme per defecte dels paràmetres de funcions és l'universal. El nombre de nivells de quantificació universal en una funció s'anomena ordre del tipus de la funció (ang: type rank). Vegeu Rank-N types (tipus d'ordre N).
El forall explícit incorpora les variables de tipus a l'àmbit de la definició fent que les variables coincidents de les restriccions de tipus internes quedin unificades.
Vegeu també
* Rank-2 types, ($) and the Monomorphism restriction
* Extensió {-# LANGUAGE NoMonomorphismRestriction #-}
* Des de GHC 7.2 Monomorfisme als lligams locals (let|where), excepte que s'expliciti la generalització.

### Tipus de Dades Algebraics Generalitzats (GADTs)

És un tipus de dades paramètric, definit amb la clàusula data on els constructors venen descrits dins una clàusula where, amb una entrada per constructor com si fos una funció, permetent que els constructors retornin subtipus (més específics) del tipus paramètric que es defineix.
Té aplicació en els llenguatges incrustats per a camps d'aplicació específics, anomenats DSL (Domain Specific Language). Requereix l'extensió de llenguatge 'GADTs'.
Vegeu
* El guany és el refinament de tipus en fer l'encaix de patrons.

### Variables d'accés no garantit (amb unsafePerformIO)

És una solució poc ortodoxa per la modificació de variables globals sense haver de passar la variable com a paràmetre, bàsicament per la modificació de preferències en temps d'execució.
De fet trenca el principi de transparència referencial de les funcions que les incorporin: constància del resultat amb les mateixes entrades, impedint l'ús de tècniques d'optimització com la memoïtzació (taules paràmetres/resultats per evitar el recàlcul).
Cal assegurar-se que la seva modificació sigui avaluada, abans de fer-ne ús, perquè el llenguatge no ho garanteix.
unsafePerformIO és la "porta del darrere" de la mònada IO.
Aquesta solució és incompatible amb la certificació Safe Haskell.
El sistema més correcte és tractar les preferències com un entorn canviant i passar-lo com a paràmetre allà on calgui, fent servir la mònada Reader o bé el transformador de mònades corresponent ReaderT.
Vegeu Compilador Haskell de Glasgow#Tractament d'un entorn canviant, amb la mònada Reader

### Classificacions dels tipus

GHC utilitza la següent nomenclatura:

#### Unboxed

    Un tipus és Unboxed (no "encapsulat en memòria dinàmica") si i només si la seva representació no és un punter.

#### Lifted

    El tipus Lifted és el dels objectes de codi, quin resultat s'avalua per encaix, on, després de provar tots els encaixos, el valor de fons (⊥) atura el programa si els encaixos no són exhaustius o bé s'hi produeix un bucle. Es diu que el tipus del resultat dels objectes de codi incorpora aquest valor (⊥).
      * Les tuples no encapsulades com a retorn (# ... #) són unlifted. Els tipus unlifted a la dreta d'una fletxa o assignació, són augmentats a Lifted implícitament.
      * Només els tipus encapsulats (representats per un punter, ang:boxed) poden ser Lifted. Però hi ha tipus encapsulats Unlifted com ara ByteArray#.

#### Data

    Un tipus declarat amb la clàusula data.

#### Algebraic

    És un tipus amb un o més constructors, encaixable amb un case, tant si s'ha creat amb data com amb newtype.

#### Primitiu

    Un tipus és primitiu si no està definit mitjançant el Haskell.

### kind

Vegeu les refs.
El kind (cat:mena) és una mena de tipus per als constructors de tipus, o, dit d'altra manera, un tipus d'ordre superior.
Defineix un conjunt de tipus,
* o bé amb una màscara que descriu l'aritat del tipus, i la dels components de tipus d'ordre superior entre parèntesis (ex.: * -> (* -> *) -> *),
       El Kind té dos constructors '*' i (->)
* o bé partint d'un conjunt de restriccions de context (kind Constraint).
* Afegit posteriorment, el kind '#'. '*' és el kind dels tipus Lifted (objectes de codi) mentre que '#' ho és dels tipus Unlifted (ex.:ByteArray#).
| expressió de tipus | kind | comentari |
| Int | * | tipus d'aritat 0 (no és funció de cap paràmetre de tipus) |
| Maybe | * -> * | constructor de tipus que és funció d'un component (Maybe a) (funció de tipus d'aritat 1) |
| Maybe Bool | * | aplicant el constructor Maybe a un tipus, tenim un tipus d'aritat 0 |
| (Int -> Double) -> Int -> Double | (* -> *) -> * -> * | quan un dels paràmetres és una funció, s'expressa entre parèntesis |
Són d'aplicació a les #Famílies de tipus, l'especificació de kind pot indicar l'aritat de la família i, en conseqüència, els paràmetres addicionals que requereixen les instàncies.
Vegeu també "GHC - Quantificació de kind explícita". Requereix extensió {-# LANGUAGE KindSignatures #-}

#### sort

Els Kind tenen una categoria que els classifica (tipus a nivell de kind) que s'anomena sort. Només hi ha un valor de sort que és BOX.
* Promoció de tipus: GHC facilita automàticament la promoció de tipus a Kinds i de constructors de tipus a constructors de Kind, amb l'extensió DataKinds.
Per indicar en una expressió que ens referim a tipus i constructors de llistes i tuples promoguts a kinds, cal prefixar-ne els identificadors amb un apòstrof.

#### kind Constraint

kind que defineix el conjunt de tipus per les restriccions de context que han de complir.
Hi ha 3 menes de restriccions:
* requeriment de visibilitat d'instància de classe en el context d'ús, com a (Show a)
* paràmetres implícits, com a (?x::Int) -- cal l'extensió ImplicitParams
* requeriment d'unificació de tipus, com a (a ~ T b) -- amb l'extensió TypeFamilies o GADTs
A partir de GHC 7.4, una especificació de restriccions de context adopta la categoria de kind Constraint i se li pot assignar un àlies.

### Famílies de tipus

Són una generalització dels tipus associats a les classes, i permeten la definició, a nivell de mòdul, dels tipus dependents d'un altre tipus, declarat com a índex de la família, que en el cas dels tipus associats correspondria al tipus índex de la classe.
L'especificació equivalent a la signatura del tipus associat duu el qualificatiu family (com data family o bé type family) mentre que la corresponent a les instàncies duen el qualificatiu instance com es detalla tot seguit.

#### Famílies de tipus estructurals

Permeten una diversificació de l'estructura, així com les classes admeten una diversificació del comportament, en instàncies per tipus.
Designen un conjunt de tipus mitjançant un constructor de família, i una variable anomenada l'índex i, opcionalment, una especificació de #kind, l'ordre del tipus.
Vegeu ref. Requereix l'extensió de llenguatge TypeFamilies.
* L'especificació de kind permet conèixer els paràmetres de tipus que cal afegir-hi:

#### Famílies de sinònims de tipus (funcions de tipus)

Les famílies de tipus especificades com a àlies (clàusula type family) defineixen funcions de tipus, quines correspondències (origen -> imatge) es concreten en instàncies de la família de tipus per casos d'encaix.
Exemple:
    Les col·leccions monomòrfiques (el seu tipus és d'aritat 0, kind '*') com ara Text, ByteString o bé IntSet no poden implementar la classe de tipus Functor ja que aquesta requereix que estiguin parametritzades pel tipus de l'element (kind * -> *).
    Això els impedeix d'implementar les classes derivades de Functor, per ex.: Foldable (per la reducció) i Traversable (per l'avaluació seqüencial dels elements si són efectes, o de les imatges d'un mapeig amb una funció d'efectes) que en depenen.
    El paquet mono-traversable hi aporta una solució basada en famílies de sinònims de tipus, que permet un tractament universal de les col·leccions, siguin o no monomòrfiques.
* Els tipus associats a les classes no són altra cosa que famílies de tipus indexades pels paràmetres de la classe dels quals depenguin

##### Famílies de sinònims de tipus tancades

Una família de sinònims de tipus amb un conjunt tancat (no ampliable) d'instàncies es pot expressar incloent les instàncies de la família en una clàusula where.

### tipus dependents de valors

Vegeu ref. Exemple a Compilador Haskell de Glasgow#Tipus dependents de valors

## Exemples
### Encapsulament estil O.O.

(Aquest enfocament ha quedat superat pel tractament d'estructures complexes amb lents (referències funcionals)).
Cercant una aproximació funcional (amb immutabilitat) a l'encapsulament de la orientació a objectes i simulació d'herència de propietats del component:
* Exemple. Els tipus d'objecte TPunt2D i TPunt3D (en terminologia Java classes (d'objectes) sense operacions), implementen (els en terminologia Java interfaces), el primer IFun2D i el segon IFun3D que requereix també IFun2D.
Un mòdul per cada tipus, encapsulant dades i operacions.
* Es pot evitar duplicar les implementacions d'alguns mètodes desacoblant-los de l'estructura, definint classes de propietats (mètodes getters/setters), i classes basades en aquestes, implementant els mètodes per defecte a la classe en un mòdul a banda, i sobreescrivint-los quan convingui a la instanciació invalidant el mètode per defecte. (ang.:overriding)
prova:
execució
* Amb la prevista incorporació del polimorfisme de "registres amb camps específics" com a requeriment de context, les classes basades en accessors de camps, es derivaran automàticament.

### Col·leccions amb components heterogenis - Emulació del despatx dels mètodes virtuals de la O.O.

Vegeu ref. El #Tipus existencial dona solució al tractament de col·leccions heterogènies incorporant els elements heterogenis com a components amb quantificació existencial (requerint que instancïin les classes que aportin la operatòria requerida), sense trencar l'homogeneïtat de les col·leccions.
dona la següent sortida:
[Just (Forma Cercle: perímetre 15.08, àrea 18.10) ,Just (Forma Rectangle: perímetre 15.00, àrea 13.64) ,Nothing]

### Entrada / Sortida amb descriptor regionalitzat

* Vegeu withFile (fitxers de text) / withBinaryFile (de System.IO) basat en la clàusula de gestió de recursos bracket amb tancament automàtic en cas d'excepció.
Exemple:
produeix la sortida següent:

### Expressions regulars

Vegeu-ho a Compilador Haskell de Glasgow#Expressions regulars

### Lents de Van Laarhoven -- consulta i manipulació de parts d'estructures complexes

Vegeu-ho a GHC

### Exemples de Fletxes (seqüenciació d'efectes basada en l'encadenament de funcions amb efectes)
#### Ent./Sort. amb fletxes de Kleisli (mònades elevades a fletxes)

Vegeu exemple a Fletxa (programació funcional)#Ent./Sort. amb fletxes de Kleisli (mònades elevades a fletxes)

#### Extreure informació d'un document XML

Vegeu exemple a Fletxa (programació funcional)

### Plantilles per a expressions, patrons, tipus i declaracions

Vegeu Compilador Haskell de Glasgow#Quasi-Quotations (Plantilles)

### Concurrència
#### Concurrència simple amb MVars - Productor-consumidor

Vegeu-ho a Haskell concurrent

#### Canals amb cues d'entrada (Chan) - Client-servidor

Vegeu exemple a Haskell concurrent

#### Concurrència condicionada amb variables transaccionals (TVar) - Mònada STM (transaccions de memòria per programari)

Vegeu exemple a Haskell concurrent

### Paral·lelisme

Vegeu Compilador Haskell de Glasgow#Paral·lelisme de tasques - Compilació per a processadors multicor

#### Paral·lelisme de tasques - Compilació per a processadors multicor

Només a GHC. Vegeu Compilador Haskell de Glasgow#Paral·lelisme de tasques - Compilació per a processadors multicor.

#### Amb Estratègies

Vegeu: Estratègies i també Reducció en paral·lel mitjançant estratègies

#### Amb la mònada Par

Vegeu Haskell concurrent#Futuribles -- Encadenament de càlculs asíncrons - la mònada Par

#### Paralel·lisme d'accions IO - El functor aplicatiu Concurrently

Vegeu Haskell concurrent#Operacions d'Entrada/Sortida asíncrones i simultànies

#### Amb paral·lelisme de dades DPH

Vegeu QuickSort amb Data Parallel Haskell

#### Ús de les instruccions SIMD sobre dades vectoritzades

Vegeu SIMD - Single Instruction, Multiple Data

#### Paral·lelisme a GPUs (GPGPU) o equivalent (via OpenCL) sobre CPUs multicor

Vegeu Paral·lelisme GPGPU

## Relacionat

* Haskell concurrent
* Mònada (programació funcional)
* Fletxa (programació funcional)
* Compilador Haskell de Glasgow

## Referències

* 1 2 Haskell.org - Lazy vs. Non-strict (anglès) Avaluació tardana i avaluació no-estricta
* ↑ «Haskell is a strict language». Arxivat de l'original el 2009-10-19. [Consulta: 24 octubre 2009].
* ↑ HaskellWiki - Thunk(anglès)
* ↑ Generalising Monads to Arrows(anglès)
* ↑ Haskell 2010(anglès) Secció 2.4 Identifiers and Operators
* ↑ Estructura lèxica del Haskell98 (anglès)
* ↑ Extensió UnicodeSyntax Arxivat 2005-11-29 a Wayback Machine.(anglès)
* ↑ H2010 - Identificadors i variables(anglès)
* ↑ Sintaxi H2010(anglès) La producció consym distingeix com a constructors aquells símbols que comencen per ':' mentre que la varsym exceptua els que comencen pel mateix caràcter.
* ↑ Haskell 2010(anglès) La producció consym està continguda en la qop dels operadors binaris infix (secció 3.4 Operator Applications)
* ↑ haskellWiki - Implicit parameters(anglès)
* ↑ Referència de sintaxi de Haskell2010(anglès)
* ↑ Haddock - Com documentar(anglès)
* ↑ Invocant Haddock - opcions(anglès)
* 1 2 Haskell 2010(anglès) Secció 1.4 Namespaces
* ↑ IEC.DLC - Sagnat
* 1 2 3 Fixity declarations(anglès) Precedències i associativitat dels operadors
* 1 2 3 Rank-2 types, ($), and the monomorphism restriction (anglès)
* ↑ Guia de classes estàndards - Instàncies derivades (anglès)
* ↑ Instàncies derivades - especificació (anglès)
* ↑ Prelude del H98 (Predefinits)(anglès) La majoria de les classes instanciables amb la clàusula deriving són aquí
* 1 2 Data.Eq(anglès)
* 1 2 3 4 Data.Ord(anglès)
* 1 2 3 Prelude#Enum(anglès)
* 1 2 3 Prelude#Bounded(anglès)
* 1 2 3 4 Data.Ix - classe dels índexs (anglès)
* 1 2 Text.Show(anglès)
* 1 2 Text.Read(anglès)
* ↑ Data.Text.Internal Internally, the Text type is represented as an array of Word16 UTF-16 code units.
* ↑ Numeric(anglès)
* 1 2 Prelude#Num(anglès)
* 1 2 Data.Bits(anglès)
* 1 2 Prelude#Real(anglès)
* 1 2 Prelude#Integral(anglès)
* 1 2 Prelude#Fractional(anglès)
* 1 2 Prelude#RealFrac(anglès)
* 1 2 Prelude#Floating(anglès)
* 1 2 Prelude#RealFloat(anglès)
* 1 2 3 Data.Ratio(anglès)
* 1 2 Data.Fixed - reals de coma fixa(anglès)
* ↑ GHC - Extensions a la clàusula deriving Arxivat 2010-04-10 a Wayback Machine.(anglès)
* ↑ Data.Bool(anglès)
* ↑ Data.Char(anglès)
* 1 2 Data.String(anglès)
* ↑ El paquet text(anglès)
* ↑ Data.Int(anglès)
* ↑ Haskell2010 - Especificació dels enters(anglès)
* ↑ Data.Word(anglès)
* ↑ Numeric.Natural(anglès)
* ↑ mòdul Data.Ratio(anglès)
* ↑ Data.Complex(anglès)
* 1 2 HaskellWiki - Unary minus(anglès)
* ↑ Ambiguous Types, and Defaults for Overloaded Numeric Operations(anglès)
* ↑ Int addition and product avoiding bad results
* ↑ Data.Word - secció Notes
* ↑ classe Integral
* ↑ Instàncies de la classe Real
* ↑ L'extensió DuplicateRecordFields(anglès)
* ↑ Extensions de GHC - Record Puns Arxivat 2005-11-29 a Wayback Machine.(anglès) simplificació de sintaxi en l'encaix dels camps dels registres
* ↑ Tuples a Haskell98(anglès)
* ↑ Data.Tuple
* ↑ Record field selector polymorphism(anglès)
* ↑ El tipus Maybe(anglès)
* ↑ El tipus Either(anglès)
* ↑ try avalua una acció que llança excepcions retornant el resultat en un tipus Either(anglès)
* 1 2 Sinònims de tipus liberals Arxivat 2010-04-25 a Wayback Machine.(anglès)
* 1 2 Llistes - Nil i Cons(anglès)
* ↑ Data.List(anglès)
* ↑ Generalised (SQL-Like) List Comprehensions Arxivat 2014-10-25 a Wayback Machine. (anglès)
* ↑ FPComplete.com - List comprehension extensions Arxivat 2014-10-25 a Wayback Machine. (anglès)
* ↑ How to pick your string library in Haskell(anglès) Com escollir la biblioteca de cadenes de caràcters en Haskell
* ↑ biblioteca "text" de tires com a vectors de caràcters de 16 bits(anglès)
* ↑ Estructura del tipus Text a Data.Text.Internal(anglès)
* 1 2 Extensió OverloadedStrings(anglès)
* ↑ La classe IsList(anglès)
* ↑ OverloadedLists(anglès)
* ↑ Lambda-case Arxivat 2016-04-13 a Wayback Machine.(anglès)
* ↑ Aplicació parcial
* ↑ HaskellWiki - Lazy evaluation (anglès)
* ↑ Pragmes Strict i StrictData(anglès)
* 1 2 3 «BangPatterns i Strict». Arxivat de l'original el 2018-08-21. [Consulta: 15 juliol 2021].
* ↑ GHC - Implicit parameters Arxivat 2012-01-30 a Wayback Machine.(anglès)
* ↑ Data.Proxy(anglès)
* ↑ serve a Servant.Server(anglès)
* 1 2 El mòdul Data.Function
* ↑ Secció (tall) d'un operador binari en infix (anglès)
* ↑ GHC Guia d'usuari - senyal de compilació: -fwarn-incomplete-patterns Arxivat 2010-03-25 a Wayback Machine.(anglès) deshabilitada per defecte
* ↑ Pattern type signatures Arxivat 2010-04-14 a Wayback Machine. (anglès)
* ↑ Pattern guards(anglès)
* 1 2 GHC users guide - Pattern synonyms Arxivat 2018-08-21 a Wayback Machine.(anglès)
* ↑ Associated pattern synonyms(anglès)
* ↑ ghc users guide - View patterns Arxivat 2016-04-13 a Wayback Machine.(anglès)
* ↑ HaskellWiki - Let vs Where
* ↑ Depuració al Haskell(anglès)
* ↑ Debug.Trace - Imprimir traces des del codi funcional(anglès)
* ↑ Debug.Trace.traceStack
* 1 2 3 haskellwiki - Orphan instance(anglès)
* ↑ haskellWiki Multiple instances(anglès)
* ↑ GHC - Stand-alone deriving Arxivat 2018-08-21 a Wayback Machine.(anglès)
* ↑ GHC users guide - DeriveAnyClass Arxivat 2016-11-20 a Wayback Machine.(anglès)
* ↑ Haskellwiki - newtype
* 1 2 HaskellWiki - Performance, Newtypes(anglès) "The newtype constructor will be optimised away."
* ↑ L'extensió GeneralizedNewtypeDeriving Arxivat 2018-08-21 a Wayback Machine.(anglès)
* ↑ Keyword arguments in Haskell(anglès)
* ↑ tipus existencials en Haskell(anglès)
* ↑ Haskell GHC - Perquè existencial Arxivat 2010-04-25 a Wayback Machine.(anglès)
* ↑ «Quantificació existencial». Arxivat de l'original el 2010-04-25. [Consulta: 15 juny 2010].
* ↑ Tipus existencial a EHC/UHC amb la paraula reservada exists Arxivat 2012-04-29 a Wayback Machine.(anglès)
* ↑ Tipus existencial al JHC amb la paraula reservada exists(anglès)
* 1 2 3 Existentially quantified - Record constructors Arxivat 2016-03-14 a Wayback Machine.(anglès)
* 1 2 Tipus existencial (anglès)
* ↑ mòdul Data.Dynamic - tipatge dinàmic bàsic(anglès)
* 1 2 Erik Meijer et al. - Functional programming with Bananas, Lenses, Envelopes and Barbed Wire(anglès)
* ↑ Haskell wiki - Newtype(anglès)
* ↑ Functor al mòdul Data.Functor(anglès)
* ↑ Set is not a Functor Arxivat 2016-02-15 a Wayback Machine.(anglès)
* ↑ Sets, Functors and Eq confusion(anglès)
* ↑ El paquet contravariant(anglès)
* ↑ El paquet profunctors(anglès)
* ↑ paquet "lens" - lents per a isomorfismes (anglès)
* ↑ Mezzolens - Lents basades en profunctors (anglès)
* ↑ MonadPlus reform proposal(anglès)
* ↑ classe Applicative(anglès)
* ↑ classe Monad(anglès)
* ↑ Biblioteca Base de GHC - vegeu mòduls marcats Base(anglès)
* 1 2 Arrows: A General Interface to Computation
* ↑ classe Category(anglès)
* ↑ classe Arrow(anglès)
* ↑ Control.Category(anglès)
* 1 2 Control.Arrow(anglès)
* ↑ Introducció planera a "Haskell XML Toolbox" (anglès)
* ↑ «Fletxes (Arrows) a GHC». Arxivat de l'original el 2007-10-14. [Consulta: 3 gener 2010].
* ↑ «Fletxes (Arrows) a l'intèrpret Hugs». Arxivat de l'original el 2009-06-16. [Consulta: 3 gener 2010].
* 1 2 Proposta MonadFail
* ↑ Control.Monad.Fail
* ↑ mòdul Data.Traversable(anglès)
* ↑ when i unless de Control.Monad(anglès)
* ↑ Throw / Catch, restriccions (anglès)
* ↑ Biblioteca exceptions(anglès)
* 1 2 Biblioteca safe-exceptions(anglès)
* ↑ Control.Exception.evaluate(anglès)
* ↑ Control.DeepSeq.force(anglès)
* ↑ Catching exceptions(anglès)
* ↑ FPComplete.com - Exceptions Best Practices in Haskell(anglès)
* ↑ Crides d'error en Ent./Sort.(anglès)
* 1 2 3 El paquet exceptions
* ↑ finally de Control.Exception(anglès)
* ↑ Novetats de la 7.6.1 - biblio. base(anglès) "The deprecated Control.OldException module has now been removed"
* ↑ Control.Exception(anglès)
* ↑ Control.Exception.catches
* ↑ Configuracions del RunTimeSystem(anglès)
* ↑ HaskellWiki - Debugging - Locating a failure in a library function(anglès)
* ↑ $(err') de File-location(anglès)
* ↑ Assercions(anglès)
* ↑ Paràmetres implícits especials(anglès)
* ↑ Notes de la versió 7.10.2(anglès)
* ↑ GHC 8.0.x Migration Guide(anglès)
* 1 2 Bottom (No finalització)
* ↑ Undefined (Implementació pendent)
* ↑ Data.IORef(anglès)
* ↑ Data.STRef(anglès)
* ↑ Control.Concurrent.MVar(anglès)
* ↑ Control.Concurrent.STM.TVar(anglès)
* ↑ Control.Concurrent.STM.TMVar(anglès)
* ↑ IORef's - referències mudables dins la mònada IO
* ↑ Top level mutable state (anglès) Estat de nivell global d'un programa
* ↑ Data.IORef atomicModifyIORef(anglès) L'ús d' atomicModifyIORef per protegir més d'una IORef està desaconsellat
* ↑ La mònada ST (anglès) efecte de canvis d'estat
* ↑ La mònada ST - referència(anglès)
* ↑ STRef's - referències a valors mudables dins la mònada ST
* ↑ Control.Monad.ST - Converting ST to IO(anglès)
* ↑ Iteratee I/O(anglès)
* ↑ Lèxic anglès sufix -er Arxivat 2021-06-04 a Wayback Machine.(anglès)
* ↑ «Lèxic anglès sufix -ee». Arxivat de l'original el 2021-07-15. [Consulta: 15 juliol 2021].
* ↑ Deterministic allocation and freeing of scarce resources(anglès) Allotjament determinista i alliberament de recursos escassos.
* ↑ Introducció als conduits Arxivat 2014-02-22 a Wayback Machine.(anglès)
* ↑ proposta MonadFail(anglès)
* ↑ GHC.IO - failIO(anglès)
* ↑ Monad - fail (implementació per defecte en la classe Monad)(anglès)
* ↑ paquet either amb el transformador EitherT(anglès)
* ↑ Eduard Kmett - Lens wiki - Overview(anglès)
* ↑ The lens library(anglès)
* ↑ HaskellWiki - Lens(anglès)
* 1 2 El paquet lens(anglès)
* ↑ History of lenses(anglès)
* ↑ Van Laarhoven - CPS Functional References(anglès)
* ↑ Edward Kmett - Consider "pure profunctor" lenses(anglès)
* ↑ Purescript profunctor lenses - Biblioteca de lents per al llenguatge PureScript (quasi-haskell compilable a JavaScript)(anglès)
* ↑ La biblio mezzolens(anglès)
* ↑ Mezzolens - La lent wander(anglès)
* ↑ Easier lenses, Profunctor based, with the Mezzolens library(anglès)
* 1 2 Mezzolens - toListOf, sumOf(anglès)
* ↑ Edward Z. Yang - The Haskell Preprocessor Hierarchy(anglès)
* ↑ HaskellWiki - Programació literària (codi inserit en documentació)(anglès)
* ↑ HaskellWiki - Alex
* ↑ HaskellWiki - Happy
* ↑ «Explicit namespaces in import/export». Arxivat de l'original el 2016-04-13. [Consulta: 15 juliol 2021].
* ↑ Importació d'instàncies
* ↑ Noms de mòdul jeràrquics Arxivat 2005-11-29 a Wayback Machine.(anglès)
* ↑ Running a compiled program Arxivat 2009-04-17 a Wayback Machine. (anglès) Paràmetres per al Run Time System
* ↑ H2010 Standard Prelude - funcions i tipus predefinits(anglès)
* ↑ H98 Standard Prelude - funcions i tipus predefinits(anglès)
* ↑ Prelude del GHC(anglès)
* ↑ API's de les biblioteques bàsiques del Haskell(anglès)
* ↑ Interfície dels vectors immutables(anglès)
* ↑ Interfície dels vectors mudables(anglès)
* ↑ Paquet vector (anglès)
* ↑ mòdul Data.Array.Parallel(anglès)
* ↑ Vectors de tractament paral·lel (paral·lelisme de dades)(anglès)
* ↑ Vectors en memòria amb accés de nivell baix(anglès)
* ↑ Vectors d'elements encapsulats(anglès)
* ↑ Vectors d'elements Unboxed (No encapsulats)(anglès)
* ↑ HaskellWiki - DiffArrays(anglès)
* ↑ Hackage - DiffArrays - Vectors per diferència(anglès)
* ↑ Vectors en memòria global (mònada IO)(anglès)
* ↑ Vectors en memòria local (mònada ST)(anglès)
* ↑ mòdul Data.Array(anglès)
* ↑ Data.Ix(anglès)
* ↑ Altres tipus de vectors a GHC (anglès)
* ↑ Extensions comunes a GHC i Hugs Arxivat 2013-01-26 a Wayback Machine. (anglès)
* ↑ Classes multiparàmetre i dependències funcionals(anglès)
* ↑ Monomorphism_restriction(anglès)
* ↑ Polimorfisme
* ↑ Rank-N types(anglès)
* ↑ Lexically scoped type variables Arxivat 2018-08-21 a Wayback Machine.(anglès)
* ↑ Guia d'extensions de GHC - ExplicitForAll
* ↑ Switching off the Monomorphism restriction Arxivat 2021-01-31 a Wayback Machine.(anglès)
* ↑ Let Generalisation in GHC 7.2(anglès) Monomorfisme als lligams locals
* ↑ «Tipus de Dades Algebraics Generalitzats (GADTs)». Arxivat de l'original el 2010-04-10. [Consulta: 7 març 2010].
* ↑ System.IO.Unsafe - unsafePerformIO(anglès)
* ↑ The Reader monad(anglès)
* ↑ Classifying Types(anglès)
* 1 2 3 4 GHC - Heap objects(anglès)
* ↑ HaskellWiki - Kind (anglès)
* ↑ Haskell's kind system - a primer
* ↑ Unlifted Data Types(anglès)
* ↑ El tipus Type i els seus col·legues(anglès)
* ↑ Explicitly-kinded quantification Arxivat 2012-01-30 a Wayback Machine.(anglès)
* 1 2 3 Promoció de tipus Arxivat 2018-08-21 a Wayback Machine.(anglès)
* ↑ «El kind Constraint». Arxivat de l'original el 2015-09-05. [Consulta: 7 desembre 2015].
* ↑ Equality constraints Arxivat 2012-08-04 a Wayback Machine.(anglès)
* ↑ Constraint Kinds for GHC(anglès)
* ↑ «GHC - Famílies de tipus». Arxivat de l'original el 2012-08-04. [Consulta: 20 desembre 2011].
* ↑ HaskellWiki - Type Families(anglès)
* ↑ mòdul Data.MonoTraversable(anglès)
* ↑ Closed type families Arxivat 2016-03-14 a Wayback Machine.(anglès)
* ↑ Dependent Types in Haskell Arxivat 2015-12-22 a Wayback Machine.(anglès)
* ↑ Polymorphism over record fields(anglès)
* ↑ OverloadedRecordFields - MagicClasses(anglès)