b'\n_START_ARTICLE_\nHaskell\n_START_SECTION_\nfonamentat en el c\xc3\xa0lcul lambda\n_START_PARAGRAPH_\nEl c\xc3\xa0lcul lambda es basa (entre d\'altres regles) en la reducci\xc3\xb3 d\'expressions, per l\'aplicaci\xc3\xb3 sistem\xc3\xa0tica d\'una funci\xc3\xb3 al primer par\xc3\xa0metre, obtenint una funci\xc3\xb3 dels par\xc3\xa0metres que li manquen._NEWLINE_Aix\xc3\xb2 facilita l\'\xc3\xbas d\'aplicacions parcials (de menys par\xc3\xa0metres del que correspon a la seva aritat), en funcions d\'ordre superior._NEWLINE_-- (->) indica retornf :: a -> r  -- indica el tipus d\'una funci\xc3\xb3 f amb par\xc3\xa0m. de tipus \'a\' que retorna un tipus \'r\'_NEWLINE_             -- els tipus en min\xc3\xbascula s\xc3\xb3n variables, _NEWLINE_             -- quan es repeteix una variable de tipus en una signatura, _NEWLINE_             -- indica que el tipus ha de coincidir amb el de la primera posici\xc3\xb3-- (->) \xc3\xa9s associatiu per la dreta:-- l\'aplicaci\xc3\xb3 parcial del primer par\xc3\xa0metre, retorna una funci\xc3\xb3 dels par\xc3\xa0metres restants(a -> b -> c) \xe2\x89\xa1 (a -> (b -> c))\n_START_SECTION_\nseparaci\xc3\xb3 d\'especificaci\xc3\xb3 i execuci\xc3\xb3\n_START_PARAGRAPH_\nEl codi d\'un m\xc3\xb2dul no s\'executa en l\'ordre d\'especificaci\xc3\xb3, sin\xc3\xb3 mitjan\xc3\xa7ant l\'avaluaci\xc3\xb3 no-estricta, partint de l\'expressi\xc3\xb3 arrel main del m\xc3\xb2dul Main que processa els arguments de la crida des de la consola de comandes.\n_START_SECTION_\navaluaci\xc3\xb3 no-estricta, normalment tardana - Thunks\n_START_PARAGRAPH_\nEn avaluaci\xc3\xb3 tardana les expressions, definides en variables i par\xc3\xa0metres, no es calculen quan es formulen sin\xc3\xb3 en el moment que se\'n demana el valor en una altra expressi\xc3\xb3. Correspon a l\'expressi\xc3\xb3 anglesa lazy evaluation._NEWLINE_Haskell \xc3\xa9s d\'avaluaci\xc3\xb3 no-estricta, que vol dir que l\'avaluaci\xc3\xb3 va de l\'arrel a les branques en l\'arbre d\'operacions de l\'expressi\xc3\xb3. L\'avaluaci\xc3\xb3 comen\xc3\xa7a per l\'expressi\xc3\xb3 definida a la cl\xc3\xa0usula main. En en cas de (b * c + a) primer s\'avalua el (+) i despr\xc3\xa9s el (*), al rev\xc3\xa9s dels llenguatges estrictes. Les altres definicions s\'avaluen sota comanda (avaluaci\xc3\xb3 tardana). D\'aquesta manera nom\xc3\xa9s s\'avaluen les subexpressions que facin falta, estalviant c\xc3\xa0lculs._NEWLINE_A la pr\xc3\xa0ctica Haskell no \xc3\xa9s un llenguatge purament tard\xc3\xa0. L\'encaix de patrons \xc3\xa9s, normalment, estricte \xe2\x80\x94almenys s\'avalua si tindr\xc3\xa0 \xc3\xa8xit\xe2\x80\x94, i un analitzador d\'\xc2\xa0estrictesa determina quan un terme ser\xc3\xa0 sempre requerit en les expressions, i converteix la seva avaluaci\xc3\xb3 en primerenca (ang.: eager evaluation) . El programador tamb\xc3\xa9 pot for\xc3\xa7ar l\'estrictesa com s\'explica m\xc3\xa9s avall._NEWLINE_Thunk \xc3\xa9s el nom de la c\xc3\xa0psula de codi corresponent a cada expressi\xc3\xb3 pendent d\'avaluar.\n_START_SECTION_\nseparaci\xc3\xb3 d\'estructura i operacions (comparat amb la POO)\n_START_PARAGRAPH_\nHaskell. a difer\xc3\xa8ncia dels lleng. amb orientaci\xc3\xb3 a objectes separa estructures de dades i comportament._NEWLINE_Els tipus de dades no impliquen operacions. Si s\xc3\xb3n simples (ex.: Int, Double), defineixen el conjunt de valors, i si s\xc3\xb3n compostos (tipus producte o tipus suma (uni\xc3\xb3 discriminada de tipus)) defineixen l\'estructura (cl\xc3\xa0usula data)._NEWLINE_Les operacions sobre el tipus poden agrupar-se en "classes de tipus", equivalents en la orientaci\xc3\xb3 a objectes a les interf\xc3\xadcies, i s\xc3\xb3n com m\xc3\xb2duls abstractes parametritzats pel tipus. Per fer-ne \xc3\xbas cal generar una inst\xc3\xa0ncia de la classe gen\xc3\xa8rica per al tipus concret, aportant la implementaci\xc3\xb3._NEWLINE_-- signaturaclass CForma t where         -- parametritzada per a un tipus t_NEWLINE_  per\xc3\xadmetre :: t -> Double   -- les variables de tipus als m\xc3\xa8todes coincidents a la declaraci\xc3\xb3 de classe_NEWLINE_  \xc3\xa0rea :: t -> Double        -- es refereixen a aquells tipus que implementin la classe.type TCostat = Double       -- \'\'type\'\' d\xc3\xb3na un \xc3\xa0lies a una expressi\xc3\xb3 de tipus-- tipus de l\'estructura, amb \'\'constructor\'\' seguit de componentsdata TRectangle = Rectangle TCostat TCostat   -- habitualment es fa servir el mateix nom per al tipus i el constructor (s\xc3\xb3n espais de noms diferents)-- implementaci\xc3\xb3 de la signatura-- generem una inst\xc3\xa0ncia del gen\xc3\xa8ric abstracte CForma per al tipus TRectangle -- que haur\xc3\xa0 d\'estar visible en l\'\xc3\xa0mbit de les expressions que en facin \xc3\xbasinstance CForma TRectangle where _NEWLINE_  per\xc3\xadmetre (Rectangle x y) = 2 * (x + y)_NEWLINE_  \xc3\xa0rea (Rectangle x y) = x * y_NEWLINE_{-# LANGUAGE NamedFieldPuns #-} -- sintaxi de literals de registres simplificadadata TPersona = Persona {nom::String, edat::Int}_NEWLINE_                   deriving (Eq, Show) -- demana al compilador que derivi inst\xc3\xa0ncies de classes b\xc3\xa0siques_NEWLINE_                                       -- partint de les representacions internes del tipus-- enumeraci\xc3\xb3: uni\xc3\xb3 de \'constructors\' d\'aritat 0 (sense par\xc3\xa0metres)data TLlenguatge = Lleng_FORTRAN | Lleng_JAVA | Lleng_HASKELL  _NEWLINE_                     deriving (Eq, Show, Ord, Enum)data TProgramador = Programador { persona::TPersona, llenguatges::[TLlenguatge] } _NEWLINE_                     deriving (Eq, Show)class CPersona t where   -- un tipus t que implementi CPersona haur\xc3\xa0 de proveir les funcions .._NEWLINE_  fer_anys :: t -> t-- defineix la classe CProgramador per aquells tipus t--    tals que (CPersona t) -- que implementin CPersona--    requereix la visibilitat, en el context d\'\xc3\xbas, d\'una inst\xc3\xa0ncia de CPersona per al tipus involucrat.class (CPersona t) => CProgramador t where_NEWLINE_  aprendre_llenguatge :: TLlenguatge -> t -> t-- generem una inst\xc3\xa0ncia de CPersona per al tipus TPersona implementant la signatura de la classe-- L\'operador (@) (variable @ patr\xc3\xb3), anomenat \'\'com el patr\xc3\xb3\'\', unifica la variable amb el valor encaixat al patr\xc3\xb3-- El lligam dels literals de camps dels registres "{camp = expressi\xc3\xb3, ...}" al constructor o variable precedent--    t\xc3\xa9 major preced\xc3\xa8ncia que l\'aplicaci\xc3\xb3 o que cap dels operadors, per aix\xc3\xb2 no cal agrupar-los entre par\xc3\xa8ntesis.instance CPersona TPersona where_NEWLINE_  fer_anys p @ Persona {edat} =   -- {edat} equival a {edat = edat} per l\'extensi\xc3\xb3 NamedFieldPuns_NEWLINE_                  p {edat = edat +1} -- el primer \xc3\xa9s el nom del camp, el segon \xc3\xa9s la variable del patr\xc3\xb3.instance CPersona TProgramador where_NEWLINE_  fer_anys prog @ Programador {persona} =_NEWLINE_                     prog {persona = fer_anys persona}instance CProgramador TProgramador where_NEWLINE_  aprendre_llenguatge llenguatge_nou prog @ Programador {llenguatges} =_NEWLINE_                          if not (llenguatge_nou `elem` llenguatges)_NEWLINE_                            then prog {llenguatges = llenguatge_nou : llenguatges}_NEWLINE_                            else prog-- valorsjoan_persona = Persona { nom="Joan", edat=50}joan_programador = Programador { persona = joan_persona, _NEWLINE_                                 llenguatges = [Lleng_FORTRAN, Lleng_JAVA] }-- l\'operador (.) de composici\xc3\xb3 de funcions permet especificar la composici\xc3\xb3 que s\'aplicar\xc3\xa0 de dreta cap a l\'esquerrafer_m\xc3\xa9s_savi = fer_anys. (aprendre_llenguatge Lleng_HASKELL) -- el punt (composici\xc3\xb3) ha d\'\xc3\xa9sser envoltat d\'espais-- l\'operador (>>>) de Control.Category permet especificar la composici\xc3\xb3 de funcions d\'esquerra a dretafer_m\xc3\xa9s_savi = (aprendre_llenguatge Lleng_HASKELL) >>> fer_anysjoan_m\xc3\xa9s_savi = fer_m\xc3\xa9s_savi joan_programadormain = print joan_m\xc3\xa9s_savi_NEWLINE_Per ser un llenguatge d\'avaluaci\xc3\xb3 no-estricta, l\'execuci\xc3\xb3 comen\xc3\xa7a per l\'avaluaci\xc3\xb3 de la cl\xc3\xa0usula d\'engegada main, calculant les expressions que calguin quan se\'n demana el valor (avaluaci\xc3\xb3 tardana) i no quan es defineix l\'expressi\xc3\xb3 (optimitzacions a banda).\n_START_SECTION_\nassociaci\xc3\xb3 \xc3\xbanica de valors a identificadors\n_START_PARAGRAPH_\nNo es poden fer dues associacions al mateix identificador en el mateix \xc3\xa0mbit (a nivell de m\xc3\xb2dul, let o where)\n_START_SECTION_\nComposici\xc3\xb3 de tipus\n_START_PARAGRAPH_\nEls tipus (conjunts de valors) es poden compondre, partint dels tipus primitius i enumeracions, en tipus producte (etiquetats: els registres; an\xc3\xb2nims: les tuples) i tipus suma (cas de variants no-parametritzades: les enumeracions; variants parametritzades: uni\xc3\xb3 discriminada), distingint-los amb un constructor que ens permetr\xc3\xa0 discriminar-los en l\'encaix de patrons. Vegeu #tipus algebraics._NEWLINE_Les fam\xc3\xadlies de tipus permeten generalitzar els tipus basant-se en un o m\xc3\xa9s \xc3\xadndexs i concretar-ne inst\xc3\xa0ncies de diferent estructura.\n_START_SECTION_\nComposici\xc3\xb3 de comportament\n_START_PARAGRAPH_\nLes classes designen la signatura (operacions) referides a variables de tipus i no a tipus concrets (com a les signatures del ML_Est\xc3\xa0ndard 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\xc3\xa0ncia de la classe per al tipus en el context d\'\xc3\xbas) (en el Java s\'esmentarien a les cl\xc3\xa0usules extends o b\xc3\xa9 implements). Vegeu #Encapsulament estil O.O.._NEWLINE_Els tipus poden aportar implementacions espec\xc3\xadfiques de la signatura d\'una classe o incorporar les implementacions per defecte definides a la classe._NEWLINE_No hi ha l\'her\xc3\xa8ncia pare/fill com entre les classes de la O.O. estalviant el temps  esmer\xc3\xa7at en el despatx per taula de m\xc3\xa8todes virtuals (vtable) i els conflictes de l\'her\xc3\xa8ncia._NEWLINE_Les implementacions poden establir requeriments de context per a les variables de tipus, addicionals als establerts a la signatura._NEWLINE_Vegeu exemple\n_START_SECTION_\nGen\xc3\xa8rics\n_START_PARAGRAPH_\nEls m\xc3\xb2duls gen\xc3\xa8rics, param\xc3\xa8trics en tipus, d\'altres llenguatges, aqu\xc3\xad prenen la forma de classes de tipus multipar\xc3\xa0metre, o b\xc3\xa9 amb tipus associats, equivalent intern de les #Fam\xc3\xadlies de tipus. Vegeu #Estructures TAD gen\xc3\xa8riques.\n_START_SECTION_\nCol\xc2\xb7leccions heterog\xc3\xa8nies\n_START_PARAGRAPH_\nLes llistes s\xc3\xb3n de tipus homogenis. Per encabir elements de tipus divers per un tractament com\xc3\xba, cal caracteritzar-los amb un tipus existencial que admeti components d\' aquells tipus que implementin la interf\xc3\xadcie que inclogui l\'operaci\xc3\xb3 que s\'hi vol aplicar.\n_START_SECTION_\nVariables\n_START_PARAGRAPH_\nHaskell disposa de variables globals IORef\'s similars a les ref del ML Est\xc3\xa0ndard, i variables STRef\'s d\'\xc3\xa0mbit local per encapsular actualitzacions destructives._NEWLINE_Per al cas de sincronitzaci\xc3\xb3 blocant, Haskell fa servir com a variables de modificaci\xc3\xb3 sincronitzada el mecanisme de comunicaci\xc3\xb3 per b\xc3\xbasties on una MVar \xc3\xa9s una b\xc3\xbastia d\'un sol element. La particularitat \xc3\xa9s que la consulta la deixa buida. Per al cas de comunicaci\xc3\xb3 amb encuament, Chan i BoundedChan s\xc3\xb3n b\xc3\xbasties amb encuament i blocatge._NEWLINE_Per la concurr\xc3\xa8ncia amb mem\xc3\xb2ria transaccional per programari (STM), hi ha les variables transaccionals TVar, TMVar (MVar\'s protegides per transaccions) i b\xc3\xbasties TChan.\n_START_SECTION_\nEfectes col\xc2\xb7laterals\n_START_PARAGRAPH_\nUna acci\xc3\xb3 amb efecte (un canvi) pot produir, a m\xc3\xa9s, un resultat computable (per ex. l\'entrada de consola: getline). El tipus de l\'efecte vindr\xc3\xa0 parametritzat pel tipus del resultat._NEWLINE_El m\xc3\xa9s emprat \xc3\xa9s l\'efecte global IO (engloba entrada/sortida, variables globals IORef\'s i tractament d\'excepcions) i el tipus d\'una acci\xc3\xb3 d\'efecte global ser\xc3\xa0 (IO tipusDelResultat)._NEWLINE_Vegeu #Efectes\n_START_SECTION_\nComposici\xc3\xb3 d\'efectes\n_START_PARAGRAPH_\nPer a les m\xc3\xb2nades vegeu Transformadors de m\xc3\xb2nades._NEWLINE_L\'equivalent per a les fletxes s\xc3\xb3n els Arrow Functors. Vegeu doc. "Generalizing Monads to Arrows".\n_START_SECTION_\nSintaxi\n_START_PARAGRAPH_\nVegeu. produccions sint\xc3\xa0ctiques del Haskell2010.\n_START_SECTION_\ncomentaris\n_START_PARAGRAPH_\n{-  comentari multil\xc3\xadnia  {- comentari niuat  -} -}_NEWLINE_ -- comentari fins a fi de l\xc3\xadnia\n_START_SECTION_\nFuncions bin\xc3\xa0ries en posici\xc3\xb3 infix en expressions\n_START_PARAGRAPH_\nQualsevol funci\xc3\xb3 de dos o m\xc3\xa9s operands es pot emprar en posici\xc3\xb3 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\xc3\xa8s s\'hi refereixen per backquotes_NEWLINE_ afegint x y = x + y_NEWLINE__NEWLINE_ valor = 4 `afegint` 3  -- l\'\xc3\xbas com a operador infix li atorga caracter\xc3\xadstiques dels operadors._NEWLINE_                        -- per defecte: associativitat per l\'esquerre i preced\xc3\xa8ncia m\xc3\xa0xima_NEWLINE_Els noms en infix admeten declaracions d\'associativitat i preced\xc3\xa8ncia, per defecte m\xc3\xa0xima preced\xc3\xa8ncia 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\xc3\xa8ncia del grup d\'operacions al qual pertanyen.\n_START_SECTION_\nTipus i classes\n_START_PARAGRAPH_\nEl tipus indica \xc3\xbanicament el domini._NEWLINE_Les classes de tipus designen un grup d\'operacions que un tipus pot implementar. La paraula reservada class introdueix un m\xc3\xb2dul gen\xc3\xa8ric de signatures d\'operacions, indexat pel par\xc3\xa0metre de tipus, amb possible implementaci\xc3\xb3 per defecte de les operacions._NEWLINE_Les classes de tipus nom\xc3\xa9s poden contenir signatures i implementacions de funcions que facin \xc3\xbas del par\xc3\xa0metre de la classe._NEWLINE_Les classes de tipus s\'assemblen als m\xc3\xb2duls gen\xc3\xa8rics de l\'Ada amb un par\xc3\xa0metre de tipus, amb l\'exclusi\xc3\xb3 de tot all\xc3\xb2 que no faci \xc3\xbas del par\xc3\xa0metre de tipus del gen\xc3\xa8ric (la classe); tamb\xc3\xa9 es poden assimilar als Interface de Java assimilant el par\xc3\xa0metre de tipus al tipus de l\'objecte Java que els ha d\'implementar._NEWLINE_class Eq t where_NEWLINE_  (==) :: t -> t -> Bool_NEWLINE_  (/=) :: t -> t -> Bool_NEWLINE__NEWLINE_  -- implementaci\xc3\xb3 per defecte_NEWLINE_  x /= y = not (x == y)_NEWLINE_  x == y = not (x /= y)_NEWLINE_  -- estan definides circularment, caldr\xc3\xa0 implementar-ne alguna de manera m\xc3\xa9s espec\xc3\xadfica, en definir-ne una inst\xc3\xa0ncia_NEWLINE__NEWLINE_  {-# MINIMAL (==) | (/=) #-} -- indicaci\xc3\xb3 de quins m\xc3\xa8todes cal implementar com a m\xc3\xadnim\n_START_SECTION_\nEl cas dels tres operadors d\'exponenciaci\xc3\xb3\n_START_PARAGRAPH_\nEl domini de l\'exponent determina el context del domini d\'aplicaci\xc3\xb3 per les operacions requerides:_NEWLINE_-- exponent natural => cal que el domini \'\'a\'\' de la base implementi el producte (definit a Num: estructura d\'anell)(^) :: (Num a, Integral ex) => a -> ex -> a  -- dispara excepci\xc3\xb3 si l\'exponent \xc3\xa9s negatiu-- exponent enter => cal que el domini de la base implementi, a m\xc3\xa9s a m\xc3\xa9s, l\'invers del producte (\'\'recip\'\': rec\xc3\xadproc) (definit a Fractional: estructura de cos)(^^) :: (Fractional a, Integral ex) => a -> ex -> a-- exponent real en coma flotant => cal que el domini de la base implementi l\'exponenciaci\xc3\xb3 (\'\'exp\'\' i \'\'log\'\': logaritme natural), definits a Floating(**) :: (Floating a, Floating ex) => a -> ex -> a\n_START_SECTION_\nliterals amb notaci\xc3\xb3 cient\xc3\xadfica\n_START_PARAGRAPH_\nDes de GHC 7.8 els sencers poden tenir literals amb notaci\xc3\xb3 cient\xc3\xadfica. Cal l\'extensi\xc3\xb3 de llenguatge NumDecimal_NEWLINE_{-# LANGUAGE NumDecimal #-}n = 1.2E4 :: Int\n_START_SECTION_\nliterals de llistes\n_START_PARAGRAPH_\n[] -- Nil (llista buida)[1,2,3] -- valors separats per comes[1..3] [\'a\'..\'z\']  -- seq\xc3\xbc\xc3\xa8ncia correlativa, tradueix a (enumFromTo 1 3) de la classe \'\'Enum\'\'[1..]  [\'a\'..]            -- tradueix a (enumFrom 1) de Enum[1,3..10] -- (== [1,3,5,7,9]) seq\xc3\xbc\xc3\xa8ncia incremental, tradueix a (enumFromThenTo 1 3 10) de Enum, tamb\xc3\xa9 admet [\'a\',\'c\'..\'z\'][1,3..]   -- tradueix a (enumFromThen 1 3) de Enum\n_START_SECTION_\ntipus algebraics\n_START_PARAGRAPH_\nCreats amb la cl\xc3\xa0usula data: Enumeracions, tipus producte, tipus suma, ...\n_START_SECTION_\nReversibilitat de tipus en registres d\'un sol component\n_START_PARAGRAPH_\n\xc3\x89s una construcci\xc3\xb3 for\xc3\xa7a utilitzada per qu\xc3\xa8 en aquests registres, el constructor i l\'accessor s\xc3\xb3n funcions inverses l\'una de l\'altra._NEWLINE_data NouTipus a = Constructor { accessor :: a}--         Constructor :: a -> NouTipus a--         accessor :: NouTipus a -> a--   (accessor. Constructor) == id_NEWLINE_Vegeu tamb\xc3\xa9 m\xc3\xa9s avall #newtype -- tipus derivats\n_START_SECTION_\nTuples\n_START_PARAGRAPH_\ntipus producte an\xc3\xb2nim amb constructors com: (,); (,,); ... . Ops. definides a Data.Tuple_NEWLINE_ ()     -- la tupla buida \xc3\xa9s un valor del tipus Unit (tipus d\'un sol valor) _NEWLINE_        -- i tamb\xc3\xa9 designa el tipus esmentat (emprat per al resultat buit en efectes (IO ()))_NEWLINE__NEWLINE_ parell = (1,"abc")  -- valor_NEWLINE_ (Int, String)    -- tipus_NEWLINE__NEWLINE_ fst parell      -- funci\xc3\xb3 primer (fst) i segon (snd) (nom\xc3\xa9s implementades per a tupla2),_NEWLINE_         -- no definit a tupla3.. i seg\xc3\xbcents_NEWLINE_ snd parell      -- segon_NEWLINE_ (,)       -- constructor de tupla2: (,) a b == (a,b)_NEWLINE_ (,,)       -- constructor de tupla3: (,,) a b c == (a,b,c)_NEWLINE_ (,,,)       -- constructor de tupla4_NEWLINE__NEWLINE_ -- encaix_NEWLINE_ (primer, segon) = parell\n_START_SECTION_\ntipus suma\n_START_PARAGRAPH_\nUni\xc3\xb3 de tipus discriminada per etiquetes (constructors), seguits dels tipus dels components_NEWLINE_ -- en aquest exemple l\'etiqueta o \'\'constructor\'\' coincideix amb el nom del tipus que el segueix_NEWLINE_ --     en diverses ocasions per\xc3\xb2 \xc3\xa9s v\xc3\xa0lid perqu\xc3\xa8 s\xc3\xb3n espais de noms diferentsdata Exception  -- aquest tipus del H98 va passar al m\xc3\xb2dul Control.OldException, que ha sigut eliminat de GHC_NEWLINE_ = IOException  IOException     -- IO exceptions_NEWLINE_ | ArithException       ArithException  -- Arithmetic exceptions_NEWLINE_ | ArrayException       ArrayException -- Array-related exceptions_NEWLINE_ | ErrorCall            String          -- Calls to \'error\'_NEWLINE_ | ExitException        ExitCode        -- Calls to \'System.exitWith\'_NEWLINE_ | NonTermination           -- Program is in an infinite loop_NEWLINE_ | UserError      String     -- General purpose exception_NEWLINE_ ...type Coord = Double-- estil algebraicdata Punt = Punt2D Coord Coord_NEWLINE_             | Punt3D Coord Coord Coord_NEWLINE_             deriving (Eq, Show)-- estil GADTs ( algebraic generalitzat) -- requereix pragma: {-# LANGUAGE GADTs #-}-- per cadascun dels constructors se\'n descriu el tipus com si fos una funci\xc3\xb3:data Punt where_NEWLINE_  Punt2D :: Coord -> Coord -> Punt_NEWLINE_  Punt3D :: Coord -> Coord -> Coord -> Punt_NEWLINE_  deriving (Eq, Show)p2D = Punt2D 2 4p3D = Punt3D 4 6 8-- encaix discriminant pel \'\'constructor\'\'m\xc3\xb2dul :: Punt -> Coordm\xc3\xb2dul (Punt2D x y) = sqrt $ x^2 + y^2m\xc3\xb2dul (Punt3D x y z) = sqrt $ x^2 + y^2 + z^2\n_START_SECTION_\nsin\xc3\xb2nims de tipus\n_START_PARAGRAPH_\nEls sin\xc3\xb2nims de tipus s\xc3\xb3n com macros al nivell de tipus._NEWLINE_type String = [Char]            -- el tipus String (cat: enfilall o tira) est\xc3\xa0 definit com a llista de car\xc3\xa0cters (seq\xc3\xbc\xc3\xa8ncia d\'acc\xc3\xa9s lineal)type LaMevaEstructura = (String, Int, Double)\n_START_SECTION_\nsin\xc3\xb2nims param\xc3\xa8trics\n_START_PARAGRAPH_\nEl seg\xc3\xbcent sin\xc3\xb2nim inclou par\xc3\xa0metres de tipus._NEWLINE_type LlistaNumerada a = [(Int, a)]\n_START_SECTION_\nllistes\n_START_PARAGRAPH_\nEl tipus Llista (seq\xc3\xbc\xc3\xa8ncia d\'acc\xc3\xa9s lineal), amb constructors "[]" (llista buida, anomenat nil) i ":" (tip_elem * llista_elem, anomenat cons) Operacions al m\xc3\xb2dul Data.List_NEWLINE_ data [a] = [] {- "nil" -} |  a : [a]   -- \':\' \xc3\xa9s el constructor "cons" (infix, per def. sint\xc3\xa0ctica)_NEWLINE__NEWLINE_ [a] -- en una decl. de tipus, llista d\'elements de tipus a_NEWLINE__NEWLINE_ []    -- llista buida_NEWLINE_ elem_cap : llista_cua_NEWLINE__NEWLINE_ [1,2,3] -- els valors han de ser homogenis (del mateix tipus)_NEWLINE_ [1,3..10] == [1, 3, 5, 7, 9]_NEWLINE__NEWLINE_ -- consultes_NEWLINE_ null xs         -- \xc3\xa9s buida?_NEWLINE_ length xs      -- mida_NEWLINE_ xs !! posici\xc3\xb3  -- el primer \xc3\xa9s llista!!0          -- funci\xc3\xb3 parcial !!_NEWLINE_ elem x xs          -- pertinen\xc3\xa7a a la llista_NEWLINE_ \xc3\xa9sFeiner dia = dia `elem` [Dl, Dm, Dc, Dj, Dv]   -- `elem` en posici\xc3\xb3 infix per les cometes revesses_NEWLINE__NEWLINE_ -- llistes infinites_NEWLINE_ [1..]_NEWLINE_ [1,3..] == [1, 3, 5, 7, 9, ...  _NEWLINE_ iterate f x == [x, f x, f (f x), ...]   -- seq\xc3\xbc\xc3\xa8ncia d\'aplicacions reiterades d\'una funci\xc3\xb3_NEWLINE_ repeat x               -- llista per repetici\xc3\xb3 del valor x_NEWLINE_ cycle xs               -- converteix la llista NO-BUIDA xs en circular -- funci\xc3\xb3 parcial !!_NEWLINE_M\xc3\xa9s operacions a contenidors\n_START_SECTION_\nllista per comprensi\xc3\xb3\n_START_PARAGRAPH_\nEspecifica l\'expressi\xc3\xb3 objectiu, obtenint-ne els valors de les variables d\'una seq\xc3\xbc\xc3\xa8ncia de generadors i filtres separats per comes_NEWLINE_ s :: [Int]_NEWLINE_ s = [ x+y | x <- [0, 2..], y <- [1, 3..20], x^2 > 3, y `mod` 9 /= 0 ]_NEWLINE__NEWLINE_ print $ take 5 s  -- imprimeix els primers\n_START_SECTION_\nllista per comprensi\xc3\xb3 mon\xc3\xa0dica\n_START_PARAGRAPH_\nLa llista per comprensi\xc3\xb3 precedent es pot expressar amb un bloc mon\xc3\xa0dic_NEWLINE_s :: [Int]s = do_NEWLINE_    x <- [0, 2..]_NEWLINE_    y <- [1, 3..20]_NEWLINE_    guard $ x^2 > 3_NEWLINE_    guard $ y `mod` 9 /= 0_NEWLINE_    return $ x+y_NEWLINE_Vegeu-ho a M\xc3\xb2nada_(programaci\xc3\xb3_funcional)#Llista_per_comprensi\xc3\xb3_mon\xc3\xa0dica\n_START_SECTION_\nllistes per comprensi\xc3\xb3 a l\'estil de SQL\n_START_PARAGRAPH_\nL\'extensi\xc3\xb3 de GHC TransformListComp permet incorporar-hi transformacions. Vegeu exemple.\n_START_SECTION_\nAplicaci\xc3\xb3 parcial\n_START_PARAGRAPH_\nVegeu ref._NEWLINE_L\'aplicaci\xc3\xb3 parcial d\'un par\xc3\xa0metre actual a una funci\xc3\xb3 causa la substituci\xc3\xb3 de la variable pel par\xc3\xa0metre en l\'expressi\xc3\xb3, resultant una funci\xc3\xb3 de les variables restants._NEWLINE_(\\ x y -> E) {- equival a -} \\ x -> (\\ y -> E)-- aplicaci\xc3\xb3 d\'una lambda a un par\xc3\xa0metre \xc3\xa9s l\'expressi\xc3\xb3 beta-redu\xc3\xafble(\\x -> E) E\'_NEWLINE_Per la reducci\xc3\xb3 beta del c\xc3\xa0lcul lambda  \xc3\xa9s la substituci\xc3\xb3 . _NEWLINE_L\'aplicaci\xc3\xb3 \xc3\xa9s associativa per l\'esquerra. f x y \xe2\x89\xa1 (f x) y_NEWLINE_L\'operador de funci\xc3\xb3 (->) "retorna" \xc3\xa9s associatiu per la dreta:_NEWLINE_(a -> b -> c) \xe2\x89\xa1 (a -> (b -> c))     -- en aplicar el primer par\xc3\xa0metre s\'obt\xc3\xa9 una funci\xc3\xb3 dels par\xc3\xa0metres restants.\n_START_SECTION_\nPas de par\xc3\xa0metres per valor\n_START_PARAGRAPH_\nVegeu #Avaluaci\xc3\xb3 estricta expl\xc3\xadcita, passar per refer\xc3\xa8ncia._NEWLINE_L\'especificaci\xc3\xb3 d\'estrictesa als par\xc3\xa0m. formals requereix l\'extensi\xc3\xb3 BangPatterns o b\xc3\xa9 la Strict._NEWLINE_-- amb indicaci\xc3\xb3 d\'avaluaci\xc3\xb3 estricta (!) als patrons{-# LANGUAGE BangPatterns #-}ident !param_formal = expressi\xc3\xb3 (param_formal)   -- def. de funci\xc3\xb3 amb estrictesa (!) als patrons (ext. BangPatterns), avalua el par\xc3\xa0metre a WHNF-- o b\xc3\xa9 amb aplicaci\xc3\xb3 estricta ($!)(ident $! param_actual)  -- = param_actual `seq` ident param_actual  -- \'seq\' avalua el primer par\xc3\xa0metre a HNF i retorna el segon-- o b\xc3\xa9 amb aplicaci\xc3\xb3 estricta a Forma Normal ($!!), avalua en profunditat, requereix que el tipus implementi NFDataimport "deepseq" Control.DeepSeq (NFData, deepseq, ($!!))(ident $!! param_actual) -- = param_actual `deepseq` ident param_actual  -- \'deepseq\' avalua el primer par\xc3\xa0metre a Forma Normal i retorna el segon_NEWLINE_L\'extensi\xc3\xb3 de llenguatge Strict de GHC 8.0 capgira el mode d\'avaluaci\xc3\xb3 dels patrons, on per defecte l\'avaluaci\xc3\xb3 ser\xc3\xa0 estricta (excepte per als identificadors a nivell de m\xc3\xb2dul "Top level bindings"), assenyalant el pas de par\xc3\xa0metres tard\xc3\xa0 (lazy) amb (~).\n_START_SECTION_\nFuncions d\'ordre superior\n_START_PARAGRAPH_\nQuan algun dels par\xc3\xa0metres \xc3\xa9s una funci\xc3\xb3:_NEWLINE_-- per descriure un par\xc3\xa0metre funci\xc3\xb3 cal acotar-lo entre par\xc3\xa8ntesis:flip :: (a -> b -> c) -> b -> a -> c    _NEWLINE_flip f x y  =  f y x_NEWLINE_Els operadors b\xc3\xa0sics sobre funcions s\xc3\xb3n al m\xc3\xb2dul Data.Function_NEWLINE_Al passar un par\xc3\xa0metre funci\xc3\xb3 no se\'n comprova l\'aritat.\n_START_SECTION_\ncasu\xc3\xadstica per encaix de patrons dels par\xc3\xa0metres\n_START_PARAGRAPH_\nEl nom de la funci\xc3\xb3 precedeix cada cas._NEWLINE_ -- _ \xc3\xa9s el comod\xc3\xad, que pot portar un sufix per a documentaci\xc3\xb3 (ex.: "_x", "_xs")_NEWLINE_ llargada :: [a] -> Int_NEWLINE_ llargada [] = 0            -- [] patr\xc3\xb3 del constructor \'\'nil\'\' de llista buida._NEWLINE_ llargada (_:xs) = 1 + llargada xs    -- (_cap : _cua) patr\xc3\xb3 del constructor \'\'cons\'\'._NEWLINE_!! GHC no avisa quan els encaixos s\xc3\xb3n incomplets (no exhaustius), excepte que ho demanis expl\xc3\xadcitament amb l\'opci\xc3\xb3 -fwarn-incomplete-patterns o -Wall_NEWLINE_La determinaci\xc3\xb3 de si un encaix \xc3\xa9s viable s\'avalua de manera estricta. Per a avaluar-los de manera tardana vegeu #Avaluaci\xc3\xb3 tardana expl\xc3\xadcita en els patrons d\'encaix\n_START_SECTION_\nl\'operador (@) - assignaci\xc3\xb3 del valor encaixat a una variable\n_START_PARAGRAPH_\nl\'operador (@), anomenat as-pattern, com a (variable @ patr\xc3\xb3) unifica la variable i el valor encaixat al patr\xc3\xb3_NEWLINE_ descriuLlista ll @ (_:_) = "llista no buida: " ++ show ll\n_START_SECTION_\nSignatures de tipus als patrons\n_START_PARAGRAPH_\nTotes les variables de patrons admeten signatures, quines variables de tipus han de pert\xc3\xa0nyer a l\'\xc3\xa0mbit de la definici\xc3\xb3._NEWLINE_  f :: forall a. [a] -> (Int, [a])_NEWLINE_  f xs = (n, zs)_NEWLINE_    where_NEWLINE_      (ys::[a], n) = (reverse xs, length xs) -- B\xc3\xa9_NEWLINE_      zs::[a] = xs ++ ys                     -- B\xc3\xa9_NEWLINE__NEWLINE_      Just (v::b) = ...  -- Incorrecte. b no est\xc3\xa0 a la vista!\n_START_SECTION_\nDefinici\xc3\xb3 per Guardes\n_START_PARAGRAPH_\nDefinici\xc3\xb3 de funcions basada en condicions_NEWLINE_ prova x_NEWLINE_     | x > 0  = 1_NEWLINE_     | x == 0 = 0_NEWLINE_     | otherwise = -1\n_START_SECTION_\nDefinici\xc3\xb3 per guardes de patrons\n_START_PARAGRAPH_\nHaskell2010. (extensi\xc3\xb3 de llenguatge PatternGuards) Permet condicionar una definici\xc3\xb3 a una seq\xc3\xbc\xc3\xa8ncia d\'encaixos subordinats._NEWLINE_Quan volem donar categoria de definici\xc3\xb3 a una expressi\xc3\xb3 subjecta a una cascada d\'encaixos_NEWLINE_addLookup env var1 var2 = _NEWLINE_  case lookup env var1 of_NEWLINE_    Just val1 -> _NEWLINE_        (case lookup env var2 of _NEWLINE_             Just val2 -> val1 + val2_NEWLINE_             Nothing -> cas_residual_NEWLINE_             )_NEWLINE_    Nothing -> cas_residual_NEWLINE_podem escriure la cascada d\'encaixos en seq\xc3\xbc\xc3\xa8ncia com a condicionant de la definici\xc3\xb3:_NEWLINE_addLookup env var1 var2_NEWLINE_   | Just val1 <- lookup env var1,_NEWLINE_     Just val2 <- lookup env var2_NEWLINE_       = val1 + val2addLookup _ _ _ = cas_residual\n_START_SECTION_\nAlternatives if, case\n_START_PARAGRAPH_\n-- if del haskell98 (en una \xc3\xbanica l\xc3\xadnia)if expr_booleana then expr1 else expr2-- if del haskell2010, es pot partir en l\xc3\xadniesif expr_booleana_NEWLINE_    then expr1_NEWLINE_    else expr2case expr of_NEWLINE_    patr\xc3\xb3 | guardaA -> exprA_NEWLINE_          | guardaB -> exprB_NEWLINE_    patr\xc3\xb32 | guarda2 -> expr2-- alternativa m\xc3\xbaltiplecase () of_NEWLINE_    _ | condici\xc3\xb31 -> expr1_NEWLINE_      | condici\xc3\xb32 -> expr2_NEWLINE_      | otherwise -> expr3-- versi\xc3\xb3 moderna (desde GHC v. 7.6.1 !!) requereix pragma d\'extensi\xc3\xb3 de llenguatge MultiWayIf:{-# LANGUAGE MultiWayIf #-}if | x == 0    -> ..._NEWLINE_   | x > 1     -> ..._NEWLINE_   | x < 0     -> ..._NEWLINE_   | otherwise -> ...\n_START_SECTION_\nIteracions funcionals sense efectes col\xc2\xb7laterals\n_START_PARAGRAPH_\nAmb recursivitat els casos queden m\xc3\xa9s clars de cara a assegurar-ne la finalitzaci\xc3\xb3. Vegeu funci\xc3\xb3 recursiva_NEWLINE_bucle params = if condici\xc3\xb3 params_NEWLINE_                   then {- cas simple -} expressi\xc3\xb3_NEWLINE_                   else {- cas recursiu -} bucle $ seg\xc3\xbcent params_NEWLINE_            where_NEWLINE_              seg\xc3\xbcent params = ...\n_START_SECTION_\nlectura de dreta a esquerra en la composici\xc3\xb3 amb (.)\n_START_PARAGRAPH_\nEn aplicar una composici\xc3\xb3 de funcions (f. g. h) obj  sobre una variable o expressi\xc3\xb3, l\'entendrem m\xc3\xa9s f\xc3\xa0cilment si les analitzem tenint en compte el tipus de l\'objecte (domini) de l\'aplicaci\xc3\xb3 i llavors les funcions que s\'hi apliquen, comen\xc3\xa7ant per l\'\xc3\xbaltima de la composici\xc3\xb3, en sentit de dreta cap a l\'esquerra._NEWLINE_Es pot escriure la composici\xc3\xb3 a l\'estil de flux de dades (d\'esquerra a dreta), amb l\'operador d\'aplicaci\xc3\xb3 cap enrere (&) definit a Data.Function desde GHC 7.10.1_NEWLINE_import Control.Exception (assert)import Control.Category ((>>>))  -- morfismes definits a la classe Category. Les funcions la implementen!import Control.Monadimport Data.Function ((&))  -- (&) = flip ($) -- infixl 1  -- desde GHC 7.10.1obj = "0"f = (++"3")g = (++"2")h = (++"1")estil0 = f (g (h obj))       -- pels aimants dels par\xc3\xa8ntesis (enyorats del LISP)estil1 = f $ g $ h obj       -- estil aplicatiuestil2 = (f. g. h) obj       -- estil funcionalestil3 = (h >>> g >>> f) obj -- estil transformacional (morfismes)estil4 = obj & h & g & f  -- estil navegaci\xc3\xb3 de dades (com a la O.O. obj.m\xc3\xa8tode),estils = [estil0, estil1, estil2, estil3, estil4]main = do_NEWLINE_         forM_ estils print              -- imprimeix el resultat de cada estil_NEWLINE_         assert comprovaci\xc3\xb3 $ print "s\xc3\xb3n iguals"_NEWLINE_       where_NEWLINE_         comprovaci\xc3\xb3 = all (== "0123") estils\n_START_SECTION_\nTra\xc3\xa7abilitat dins el codi funcional\n_START_PARAGRAPH_\nEl codi funcional no permet l\'\xc3\xbas de print (efecte col\xc2\xb7lateral). Cal fer servir trace o b\xc3\xa9 traceStack del m\xc3\xb2dul Debug.Trace. Imprimeix el primer par\xc3\xa0metre, via unsafePerformIO i retorna el segon._NEWLINE_Atenci\xc3\xb3: l\'ordre d\'execuci\xc3\xb3 de subexpressions en codi funcional \xc3\xa9s indeterminat, i igualment ho ser\xc3\xa0 l\'ordre d\'impressi\xc3\xb3 de les traces._NEWLINE_En codi mon\xc3\xa0dic (seq\xc3\xbcencial), l\'ordre d\'impressi\xc3\xb3 de les traces, est\xc3\xa0 subjecte al moment de l\'avaluaci\xc3\xb3 que, per \xc3\xa9sser tardana, \xc3\xa9s dif\xc3\xadcil de predir amb seguretat._NEWLINE_-- prova.hsimport Debug.Trace (trace)    -- trace :: String -> a -> aquadrat x = trace msg resultat_NEWLINE_  where_NEWLINE_    msg = "tra\xc3\xa7a de quadrat: x: " ++ show x ++ " resultat: " ++ show resultat_NEWLINE_    resultat = x * xcub x = x * quadrat xmain = putStrLn $ "cub de 2: " ++  show (cub 2)_NEWLINE_A partir de GHC v.7.4.1 hi ha tamb\xc3\xa9 traceStack\xc2\xa0:: String -> a -> a que a m\xc3\xa9s bolca la tra\xc3\xa7a de crides si s\'ha compilat amb opcions de perfilat._NEWLINE_Substitu\xc3\xafm trace per traceStack i ..._NEWLINE_ghc --make -prof -fprof-auto-calls prova.hs_NEWLINE_./prova_NEWLINE_tra\xc3\xa7a de quadrat: x: 2 resultat: 4_NEWLINE_Stack trace:_NEWLINE_  Main.quadrat.resultat\' (prova.hs:6:17-39)_NEWLINE_  Main.cub (prova.hs:10:13-21)_NEWLINE_  Main.cub (prova.hs:10:9-21)_NEWLINE_  Main.main (prova.hs:12:42-46)_NEWLINE_  Main.main (prova.hs:12:36-47)_NEWLINE_  Main.main (prova.hs:12:19-47)_NEWLINE_  Main.main (prova.hs:12:8-47)_NEWLINE_  Main.CAF (<entire-module>)_NEWLINE_cub de 2: 8\n_START_SECTION_\nEspecialitzaci\xc3\xb3, instanciaci\xc3\xb3 per tipus\n_START_PARAGRAPH_\nL\'\xc3\xbas d\'operacions que no s\xc3\xb3n de la pr\xc3\xb2pia classe a les implementacions per defecte, fa necessari requerir la pres\xc3\xa8ncia, en el context d\'\xc3\xbas, d\'inst\xc3\xa0ncies de les classes que incorporen les operacions._NEWLINE_-- per aquells tipus t que implementin les classes requeridesclass (ClasseRequeridaA t, ClasseRequeridaB t, ...) => ClasseNova t where ..._NEWLINE_{-# LANGUAGE NamedFieldPuns #-}  -- simplificaci\xc3\xb3 en literals de registres _NEWLINE_                        -- (interpreta \'camp\' seguit de separador o delimitador, com a \'camp = camp\' )class PropXY t where_NEWLINE_  getXY :: t -> (Int, Int)_NEWLINE_  setXY :: Int -> Int -> t -> t-- funcionalitat 2D requereix que el tipus implementi PropXYclass (PropXY t) => IFun2D t where_NEWLINE_  despla\xc3\xa7a2D :: Int -> Int -> t -> t_NEWLINE__NEWLINE_  -- implementaci\xc3\xb3 per defecte a la classe_NEWLINE__NEWLINE_  despla\xc3\xa7a2D dx dy punt = setXY (x+dx) (y+dy) punt_NEWLINE_    where_NEWLINE_      (x,y) = getXY puntdata TPunt2D = Punt2D {x, y ::Int}instance PropXY TPunt2D where_NEWLINE_  getXY Punt2D {x, y} = (x, y)_NEWLINE_  setXY x y punt = punt {x, y} -- equival a punt {x = x, y = y}instance IFun2D TPunt2D  -- genera una inst\xc3\xa0ncia per a TPunt2D amb la implementaci\xc3\xb3 per defecte_NEWLINE_Vegeu exemple m\xc3\xa9s complet m\xc3\xa9s avall\n_START_SECTION_\nInstanciaci\xc3\xb3 gen\xc3\xa8rica\n_START_PARAGRAPH_\nQuan totes les operacions es basen en operacions de les classes base i no en particularitats d\'un tipus, es pot definir la instanciaci\xc3\xb3 a nivell de classe amb efecte autom\xc3\xa0tic. (Requereix l\'extensi\xc3\xb3 de llenguatge UndecidableInstances)._NEWLINE_{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}class PropXY t where_NEWLINE_  getXY :: t -> (Int, Int)_NEWLINE_  setXY :: Int -> Int -> t -> tclass IFun2D t where_NEWLINE_  despla\xc3\xa7a2D :: Int -> Int -> t -> tinstance (PropXY t) => IFun2D t where    -- (IFun2D t) ser\xc3\xa0 autom\xc3\xa0tic per a tot tipus t tal que (PropXY t)_NEWLINE_  despla\xc3\xa7a2D dx dy punt = setXY (x+dx) (y+dy) punt_NEWLINE_    where_NEWLINE_      (x,y) = getXY punt\n_START_SECTION_\nDerivaci\xc3\xb3 d\'inst\xc3\xa0ncies per a tipus param\xc3\xa8trics amb requeriments\n_START_PARAGRAPH_\nAmb l\'extensi\xc3\xb3 de llenguatge StandaloneDeriving el compilador permet que afegeixis requeriments de context a la derivaci\xc3\xb3 d\'inst\xc3\xa0ncies amb cl\xc3\xa0usules deriving independents de la definici\xc3\xb3 de l\'estructura._NEWLINE_{-# LANGUAGE StandaloneDeriving #-}data Foo a = Bar a | Baz Stringderiving instance Eq a => Eq (Foo [a])deriving instance Eq a => Eq (Foo (Maybe a))\n_START_SECTION_\nDerivaci\xc3\xb3 r\xc3\xa0pida d\'inst\xc3\xa0ncies de classes amb implementaci\xc3\xb3 per defecte\n_START_PARAGRAPH_\nL\'extensi\xc3\xb3 DeriveAnyClass ho permet. Si Bar \xc3\xa9s una classe on tots els m\xc3\xa8todes tenen implementaci\xc3\xb3 per defecte_NEWLINE_data Foo = Foo ...instance Bar Foo  -- sense implementaci\xc3\xb3 espec\xc3\xadfica_NEWLINE_es pot escriure en una sola l\xc3\xadnia (a banda de la pragma d\'extensi\xc3\xb3 de llenguatge)_NEWLINE_{-# LANGUAGE DeriveAnyClass #-}data Foo = Foo ... deriving (Bar)_NEWLINE_Exemple a Compilador Haskell de Glasgow#serialitzaci\xc3\xb3 en format JSON\n_START_SECTION_\n\xc3\xbas dels newtypes predefinits\n_START_PARAGRAPH_\nEls tipus All i Any definits amb newtype per als quals s\'implementa un Monoide per a la conjunci\xc3\xb3 o b\xc3\xa9 disjunci\xc3\xb3, permeten un tractament similar en definir els seg\xc3\xbcents quantificadors de col\xc2\xb7leccions basats en propietats._NEWLINE_Apliquem el constructor adequat (All o b\xc3\xa9 Any) als valors i el plegat amb monoide far\xc3\xa0 servir l\'op. definida per al newtype corresponent. En acabat, caldr\xc3\xa0 convertir el tipus del resultat amb la inversa del constructor: l\'accessor._NEWLINE_{-| \xc3\x9as dels newtype All i Any predefinits a Data.Monoid-}import Data.Function ((&))        -- (&) = flip ($)   -- aplicaci\xc3\xb3 cap enrereimport Control.Category ((>>>))   -- f >>> g = g. f   -- composici\xc3\xb3 esq. a dretaimport Data.Monoid (All(..), Any(..)){-| -- de la definici\xc3\xb3 a Data.Monoidnewtype All = All { getAll :: Bool }  -- implementa monoid per a la conjunci\xc3\xb3 (&&)        deriving (Eq, Ord, Read, Show, Bounded, Generic)newtype Any = Any { getAny :: Bool }  -- implementa monoid per a la disjunci\xc3\xb3 (||)       deriving (Eq, Ord, Read, Show, Bounded, Generic)-- de Data.FoldablefoldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m-}existeix, perATots :: Foldable t => (a -> Bool) -> t a -> Bool-- convertint la sortida de \'prop\' al Monoide adequat, i reconvertint el resultat:existeix prop xs = foldMap (prop >>> Any) xs & getAnyperATots prop xs = foldMap (prop >>> All) xs & getAll\xc3\xa9sParell :: Integral t => t -> Bool\xc3\xa9sParell x = x `mod` 2 == 0-- versi\xc3\xb3 t\xc3\xa0cita (sense param. formals redu\xc3\xafbles)\xc3\xa9sParell = (`mod` 2) >>> (== 0)default (Int)                 -- desambiguaci\xc3\xb3 literals num\xc3\xa8rics mostra = [1,2,3]main = do_NEWLINE_     print $ existeix \xc3\xa9sParell mostra_NEWLINE_     print $ perATots \xc3\xa9sParell mostra\n_START_SECTION_\ntipus derivats de funcions\n_START_PARAGRAPH_\nTamb\xc3\xa9 s\'utilitza per definir un tipus com a abstracci\xc3\xb3 d\'un tipus de funci\xc3\xb3. Aix\xc3\xb2 permet definir operacions de combinaci\xc3\xb3 de funcions del tipus espec\xc3\xadfic, com a les  Fletxes_NEWLINE_ -- sigui, per exemple, f :: a -> [b]  -- el tipus de funci\xc3\xb3 sobre el que volem definir operacions_NEWLINE_ --           x :: a_NEWLINE__NEWLINE_ newtype TFiltre a b = Filtre { runFiltre :: a -> [b] }_NEWLINE__NEWLINE_ -- Constructor:               Filtre  :: (a -> [b]) -> TFiltre _NEWLINE_ -- Inversa del constructor:   runFiltre :: TFiltre -> (a -> [b])   _NEWLINE__NEWLINE_ filtre_f = Filtre f       -- element del nou tipus aplicant el constructor a la funci\xc3\xb3_NEWLINE__NEWLINE_ runFiltre filtre_f       -- retorna la funci\xc3\xb3 f original, aplicant la \'\'inversa_del_constructor\'\'_NEWLINE__NEWLINE_ runFiltre filtre_f x      -- aplica la funci\xc3\xb3 original a x\n_START_SECTION_\nLlistes homog\xc3\xa8nies d\'elements amb components heterogenis\n_START_PARAGRAPH_\nVegeu. El #Tipus existencial permet definir tipus de dades polim\xc3\xb2rfics amb components caracteritzats per admetre un mateix grup d\'operacions._NEWLINE_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._NEWLINE_Cal especificar l\'opci\xc3\xb3 de compilaci\xc3\xb3 "-XExistentialQuantification" o la pragma {-# LANGUAGE ExistentialQuantification #-}_NEWLINE_{-# LANGUAGE ExistentialQuantification #-}_NEWLINE__NEWLINE_ -- tipus amb constructor Obj i un component_NEWLINE_ --    d\'aquells tipus \'\'a\'\' que implementin la classe Show_NEWLINE__NEWLINE_ data ObjPresentable = forall a. (Show a) => Obj a_NEWLINE__NEWLINE_ llistaHetero :: [ObjPresentable]_NEWLINE_ llistaHetero = [Obj 1, Obj "foo", Obj \'c\']_NEWLINE__NEWLINE_ mostra :: [ObjPresentable] -> String_NEWLINE_ mostra [] = ""_NEWLINE_ mostra (Obj x : []) = show x  -- mostra el darrer (la cua \xc3\xa9s buida)_NEWLINE_ mostra (Obj x : xs) = show x ++ ", " ++ mostra xs  -- aplica al component x l\'operaci\xc3\xb3 show_NEWLINE_                                            -- de la classe Show que el component d\'Obj implementa_NEWLINE_ main = putStrLn $ mostra llistaHetero---------- amb derivaci\xc3\xb3 autom\xc3\xa0tica d\'inst\xc3\xa0nciesderiving instance Show ObjPresentable    -- la derivaci\xc3\xb3 d\'inst\xc3\xa0ncies dels objectes existencials va separadamain = print llistaHetero_NEWLINE_Vegeu-ne l\'exemple #Col\xc2\xb7leccions amb components heterogenis - Emulaci\xc3\xb3 del despatx dels m\xc3\xa8todes virtuals de la O.O.\n_START_SECTION_\nTipatge din\xc3\xa0mic - Par\xc3\xa0metres de tipus divers\n_START_PARAGRAPH_\nHaskell admet pas de par\xc3\xa0metres amb control del tipus en temps d\'execuci\xc3\xb3, nom\xc3\xa9s per a tipus monom\xc3\xb2rfics (sense variables de tipus)._NEWLINE_Exemple amb l\'\xc3\xbas de l\'extensi\xc3\xb3 ViewPatterns (Vegeu #Patrons de vistes)_NEWLINE_{-# LANGUAGE ViewPatterns, ScopedTypeVariables #-}import Data.Dynamic-- fromDynamic :: Dynamic -> Maybe a  -- per obtenir un resultat, cal provar-ho amb restricci\xc3\xb3 de tipus: -- control din\xc3\xa0mic del tipus del par\xc3\xa0metre, farem servir ViewPatterns: \'\'(vista -> patr\xc3\xb3)\'\' sobre el par\xc3\xa0metre.printDynamic :: Dynamic -> IO ()printDynamic (fromDynamic -> Just (x :: Int)) = putStrLn $ "era un Int: " ++ show xprintDynamic (fromDynamic -> Just (x :: Float)) = putStrLn $ "era un Float: " ++ show xprintDynamic (fromDynamic -> Just (xy :: (Int, Int))) = putStrLn $ "era un parell de Ints: " ++ show xyprintDynamic (fromDynamic -> Just (xs :: [Int])) = putStrLn $ "era una llista de Ints: " ++ show xsprintDynamic (fromDynamic -> Just (f :: (Int -> Int))) = putStrLn $ "era una funci\xc3\xb3 (Int -> Int): 2 -> " ++ show (f 2)printDynamic _ = error "printDynamic: tipus inesperat"main = do_NEWLINE_          printDynamic $ toDyn (1 :: Int)_NEWLINE_          printDynamic $ toDyn (-2.5 :: Float)_NEWLINE_          printDynamic $ toDyn ((2, 3) :: (Int, Int))_NEWLINE_          printDynamic $ toDyn ([1..3] :: [Int])_NEWLINE_          printDynamic $ toDyn ((*2) :: Int -> Int)_NEWLINE_d\xc3\xb3na_NEWLINE_$ runhaskell prova3_NEWLINE_era un Int: 1_NEWLINE_era un Float: -2.5_NEWLINE_era un parell de Ints: (2,3)_NEWLINE_era una llista de Ints: [1,2,3]_NEWLINE_era una funci\xc3\xb3 (Int -> Int): 2 -> 4\n_START_SECTION_\nSeq\xc3\xbc\xc3\xa8ncies i col\xc2\xb7leccions en codi funcional pur\n_START_PARAGRAPH_\nAlgunes de les funcions seg\xc3\xbcents incorporen en la funci\xc3\xb3 nucli de la iteraci\xc3\xb3 un par\xc3\xa0metre a l\'entrada i a la sortida interpretable com a estat de la iteraci\xc3\xb3, que evoluciona partint d\'un valor inicial llavor per l\'aplicaci\xc3\xb3 reiterada de la funci\xc3\xb3 nucli.\n_START_SECTION_\nSeq\xc3\xbc\xc3\xa8ncies - generaci\xc3\xb3 d\'una seq\xc3\xbc\xc3\xa8ncia partint d\'un valor\n_START_PARAGRAPH_\n\xc3\x89s la particularitzaci\xc3\xb3 de Haskell d\'un Anamorfisme o desplegament d\'estructures: (b -> a*)._NEWLINE_-- en un anamorfisme que forma una llista:anamorf :: (estat -> (valor, estat)) -> (estat -> Bool) -> estat -> [valor]anamorf desplega \xc3\xa9sFinal estat =_NEWLINE_  if \xc3\xa9sFinal estat_NEWLINE_     then []_NEWLINE_     else valor : (anamorf desplega \xc3\xa9sFinal estat\')_NEWLINE_          where (valor, estat\') = desplega estat_NEWLINE_Amb la funci\xc3\xb3 unfoldr ("unfold right", cat: desplega per la dreta) de Data.List. La seq\xc3\xbc\xc3\xa8ncia s\'acaba quan la funci\xc3\xb3 nucli no retorna valor (Nothing)._NEWLINE_unfoldr :: (llavor -> Maybe (item, llavor {-seg\xc3\xbcent-})) ->   -- funci\xc3\xb3 nucli per obtenir opcionalment el seg\xc3\xbcent \'\'\xc3\xadtem\'\'_NEWLINE_           llavor {-inicial-} -> _NEWLINE_           [item]\n_START_SECTION_\nSeq\xc3\xbc\xc3\xa8ncies - transformaci\xc3\xb3 d\'una seq\xc3\xbc\xc3\xa8ncia amb mem\xc3\xb2ria\n_START_PARAGRAPH_\nAmb mapAccumL de Data.List, podem especificar la funci\xc3\xb3 nucli de la iteraci\xc3\xb3, que partint d\'un estat i un element de la seq\xc3\xbc\xc3\xa8ncia ens proporcioni l\'estat inicial de la seg\xc3\xbcent iteraci\xc3\xb3, i l\'element de la seq\xc3\xbc\xc3\xa8ncia de sortida._NEWLINE_mapAccum{L|R} :: (llavor -> item -> (llavor {-seg\xc3\xbcent-}, item\')) ->   -- funci\xc3\xb3 nucli de la iteraci\xc3\xb3_NEWLINE_                 llavor {-inicial-} -> _NEWLINE_                 [item] {-inicial-} -> _NEWLINE_                 (llavor {-final-}, [item\'])\n_START_SECTION_\nCol\xc2\xb7leccions - composici\xc3\xb3 - les classes Semigroup i Monoid\n_START_PARAGRAPH_\nDes de GHC 8.0 s\'ha incorporat al paquet base l\'estructura Semigrup en un m\xc3\xb2dul Data.Semigroup amb una operaci\xc3\xb3 associativa definida per (<>) amb associativitat infixr 6 <>._NEWLINE_Abans ja ten\xc3\xadem la classe Monoid de Data.Monoid on mappend \xc3\xa9s l\'operaci\xc3\xb3 associativa que en posici\xc3\xb3 infix (`mappend`) processa associant per l\'esquerra (assoc. per defecte: infixl 9), mentre que tamb\xc3\xa9 es defineix (<>) com a sin\xc3\xb2nim que processa associant per la dreta (infixr 6 <>)._NEWLINE_Exemple sobre llistes, conjunts i diccionaris (tots ells implementen les classes Semigroup i Monoid). Els vectors del paquet vector tamb\xc3\xa9._NEWLINE_ghciPrelude> import Data.SemigroupPrelude Data.Semigroup> [1,2] <> [3,4]              -- composici\xc3\xb3 de llistes[1,2,3,4]Prelude Data.Semigroup>:set -XOverloadedLists       -- extensi\xc3\xb3 OverloadedLists per l\'\xc3\xbas de literals llistes en altres tipusPrelude Data.Semigroup> import Data.Set as SPrelude Data.Semigroup S> import Data.Map as MPrelude Data.Semigroup S M> import Data.Vector as VPrelude Data.Semigroup S M V> ([1,2] :: Vector Int) <> ([3,4] :: Vector Int) -- composici\xc3\xb3 de vectors[1,2,3,4]Prelude Data.Semigroup S M V> ([1,2] :: Set Int) <> ([2,3] :: Set Int)       -- composici\xc3\xb3 de conjuntsfromList [1,2,3]Prelude Data.Semigroup S M V> ([(1,"a"), (2,"b")] :: Map Int String) <> ([(2,"b\'"), (3,"c\'")] :: Map Int String)  -- composici\xc3\xb3 de diccionarisfromList [(1,"a"),(2,"b"),(3,"c\'")]\n_START_SECTION_\nLa classe Bifunctor\n_START_PARAGRAPH_\nDes de GHC 8.2 el paquet base est\xc3\xa9n els Functors a les col\xc2\xb7leccions d\'elements amb domini dual (per ex.: Either a b) amb mapeig que incorpora funcions per cadascun dels dominis. Del m\xc3\xb2dul Data.Bifunctor_NEWLINE_class Bifunctor p where_NEWLINE__NEWLINE_  bimap :: (a -> b) -> (c -> d) -> p a c -> p b d_NEWLINE__NEWLINE_  first :: (a -> b) -> p a c -> p b c_NEWLINE_  second :: (b -> c) -> p a b -> p a c\n_START_SECTION_\nFunctors contravariants - la classe Contravariant\n_START_PARAGRAPH_\nQuan el contingut del contenidor \xc3\xa9s una funci\xc3\xb3, es pot definir un Functor sobre el domini dels arguments (posicions contravariants) de la funci\xc3\xb3._NEWLINE_La covarian\xc3\xa7a i contravarian\xc3\xa7a es fa servir m\xc3\xa9s als llenguatges que implementen subtipatge. Subtipatge, covarian\xc3\xa7a i contravarian\xc3\xa7a a Scala_NEWLINE_Al paquet contravariant._NEWLINE_newtype Predicat a = Predicat {getPredicat :: a -> Bool}   -- tipus \'a\' en posici\xc3\xb3 contravariantnewtype Comparaci\xc3\xb3 a = Comparaci\xc3\xb3 {getComparaci\xc3\xb3 :: a -> a -> Ordering}   -- tipus \'a\' en posici\xc3\xb3 contravariant-- Donada una relaci\xc3\xb3 \'f\' en el conjunt del tipus \'b\', una projecci\xc3\xb3 (a -> b) estableix la relaci\xc3\xb3 en el conjunt del tipus \'a\' entre aquells elements quines imatges formin part de la relaci\xc3\xb3.class Contravariant f where_NEWLINE_  contramap :: (a -> b) -> f b -> f a_NEWLINE_  ...-- contramap sobre el newtype Comparaci\xc3\xb3, que defineix una relaci\xc3\xb3 d\'ordre, confereix ordenaci\xc3\xb3 al domini origen de la projecci\xc3\xb3-- per exemple: una projecci\xc3\xb3 sobre parells:ghciPrelude> import Data.Functor.Contravariant as CPrelude C> import Data.Function as F ((&))-- apliquem amb "contramap" una projecci\xc3\xb3 "snd" cap al domini contravariant de Comparison, obtenint un Comparison sobre l\'origen de la projecci\xc3\xb3, els parellsPrelude C F> let f = contramap snd (Comparison compare) _NEWLINE_Prelude C F> :t f   -- el tipus del resultat \xc3\xa9s Comparison sobre parells, comparant pel segon de la tuplaf :: Ord a1 => Comparison (a, a1)\n_START_SECTION_\nEfectes aplicatius\n_START_PARAGRAPH_\nEfectes que implementen la classe Applicative.\n_START_SECTION_\nEfectes mon\xc3\xa0dics\n_START_PARAGRAPH_\nEfectes que implementen la classe Monad.\n_START_SECTION_\nEfectes fletxa\n_START_PARAGRAPH_\nVegeu ref._NEWLINE_Una fletxa, concepte desenvolupat per John Hughes, \xc3\xa9s una generalitzaci\xc3\xb3 d\'una funci\xc3\xb3 on el resultat pot dependre d\'efectes col\xc2\xb7laterals o b\xc3\xa9 ser independent de l\'entrada. Es concreta en les classes Category (que generalitza les funcions amb par\xc3\xa0metres pel tipus de l\'entrada i de la sortida) i la seva especialitzaci\xc3\xb3 Arrow que refina les categories amb el tractament de parells, necessari per combinar-ne resultats. Vegeu Fletxa (programaci\xc3\xb3 funcional)#Fletxes i Parells\n_START_SECTION_\nEntrada / Sortida - M\xc3\xb2nades\n_START_PARAGRAPH_\nLes operacions d\'entrada/sortida produeixen efectes a l\'entorn i un resultat program\xc3\xa0tic 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 () )._NEWLINE_Per la seq\xc3\xbcenciaci\xc3\xb3 d\'operacions s\'utilitza preferentment la classe m\xc3\xb2nada sobre el tipus (IO a), donant lloc a la m\xc3\xb2nada IO._NEWLINE_La funci\xc3\xb3 inicial main de qualsevol programa ha de ser una expressi\xc3\xb3 d\'operacions d\'ent./sortida i per tant del tipus de la m\xc3\xb2nada IO._NEWLINE_La funci\xc3\xb3 evaluate permet seq\xc3\xbcenciar com a efecte IO, les excepcions que pot llan\xc3\xa7ar una expressi\xc3\xb3 funcional pura._NEWLINE_Les accions de lectura/escriptura de variables globals IORef tamb\xc3\xa9 formen part dels efectes IO._NEWLINE_ -- expressions de la \'\'m\xc3\xb2nada\'\' IO (el tipus porta com a par\xc3\xa0metre el tipus del resultat de les operacions)_NEWLINE_ getLine            -- captura l\xc3\xadnia d\'entrada amb resultat String -- tipus \'\'IO String\'\'_NEWLINE_ getLine >>= putStr        -- imprimeix l\xc3\xadnia introdu\xc3\xafda (resultat buit) -- tipus \'\'IO ()\'\'_NEWLINE_ putStr "polseu Intro" >> getLine >> putStrLn "Fet" >> return True    -- (resultat de la cadena: boole\xc3\xa0) tipus \'\'IO Bool\'\'_NEWLINE_ return "abc" >>= putStrLn   -- estableix "abc" com a resultat mon\xc3\xa0dic i l\'imprimeix tot seguit_NEWLINE__NEWLINE_ -- >>= -- encadena amb una funci\xc3\xb3 efecte que s\'aplica al resultat de l\'efecte precedent_NEWLINE_ -- >>  -- encadena amb un altre efecte, ignorant el resultat del precedent_NEWLINE_ -- return x  -- op. generadora d\'una m\xc3\xb2nada amb resultat x quedant del tipus IO X_NEWLINE_        -- no pressuposa \'\'retorn\'\' d\'enlloc; per ex. (return 5 >>= print)_NEWLINE__NEWLINE_ -- fail missatge  -- cridada internament, cas que el patr\xc3\xb3 a l\'esquerra de (<-) en un bloc \'do\' no sigui exhaustiu._NEWLINE_ -- des de GHC 8.0 la funci\xc3\xb3  \'fail\' se separa de la classe Monad i va a la classe MonadFail amb inst\xc3\xa0ncies per als tipus IO i Maybe.\n_START_SECTION_\nAlternatives en efectes - Blocs do niuats\n_START_PARAGRAPH_\nPer posar m\xc3\xa9s d\'una instrucci\xc3\xb3 en una branca d\'un "case" o d\'un "if" cal agrupar-les dins un subbloc "do"_NEWLINE_Les funcions when i unless de Control.Monad proporcionen l\'avaluaci\xc3\xb3 condicionada d\'un efecte.\n_START_SECTION_\nRecursivitat en els blocs do\n_START_PARAGRAPH_\nVegeu M\xc3\xb2nada_(programaci\xc3\xb3_funcional)#Recursivitat_en_els_blocs_do\n_START_SECTION_\nLlan\xc3\xa7adors\n_START_PARAGRAPH_\nthrow   :: Exception e => e -> a           -- llan\xc3\xa7a excep en el codi funcional purthrowIO :: Exception e => e -> IO a        -- llan\xc3\xa7a excep. en el context de la m\xc3\xb2nada IO (efecte global)ioError :: IOError -> IO a                 -- llan\xc3\xa7a una excepci\xc3\xb3 IOError-- afegeix localitzaci\xc3\xb3 i informacions a un IOErrorannotateIOError :: IOError -> String -> Maybe Handle -> Maybe FilePath -> IOError_NEWLINE_Vegeu errors I/O.\n_START_SECTION_\nbracket i avaluaci\xc3\xb3 tardana\n_START_PARAGRAPH_\nUn error com\xc3\xba amb l\'Ent./Sortida tardana \xc3\xa9s el seg\xc3\xbcent:_NEWLINE_A l\'exemple seg\xc3\xbcent hGetContents no s\'avalua fins que no s\'avalu\xc3\xaf el withFile, per\xc3\xb2 com que no entrega el contingut si no li ho demanen, bracket (withFile \xc3\xa9s aplicaci\xc3\xb3 parcial de bracket) tanca el recurs. El resultat \xc3\xa9s la sortida buida. El compilador no avisa de l\'error\xc2\xa0!!_NEWLINE_La versi\xc3\xb3 correcta \xc3\xa9s ficar el consumidor dins l\'acci\xc3\xb3 vetllada pel bracket, \xc3\xa9s a dir, el bloc del withFile, consumint el contingut abans no es tanqui el recurs._NEWLINE_{-| fitxer prova.hs -}import System.IO (withFile, IOMode(ReadMode), hGetContents)import Data.Function ((&)) -- aplicaci\xc3\xb3 cap enrere (infixl 1)-- imprimeix nombre de l\xc3\xadnies llegidesincorrecte = do_NEWLINE_    contingut <- withFile "test.txt" ReadMode hGetContents_NEWLINE_    let nombreDeL\xc3\xadnies = contingut & lines & length_NEWLINE_    print nombreDeL\xc3\xadniescorrecte = do_NEWLINE_    withFile "test.txt" ReadMode $ \\hd -> do_NEWLINE_        contingut <- hGetContents hd_NEWLINE_        let nombreDeL\xc3\xadnies = contingut & lines & length_NEWLINE_        print nombreDeL\xc3\xadnies-- fi de fitxer-- fitxer test.txtabc-- fi de fitxerghciPrelude> :l prova                  -- carrega i compila el codi precedent[1 of 1] Compiling Main             ( prova.hs, interpreted )Ok, modules loaded: Main.*Main> incorrecte*** Exception: test.txt: hGetContents: illegal operation (delayed read on closed handle)*Main> correcte1\n_START_SECTION_\ntry - avaluaci\xc3\xb3 i an\xc3\xa0lisi per casos de les expressions llan\xc3\xa7adores d\'excepcions\n_START_PARAGRAPH_\ntry avalua un efecte IO que pot llan\xc3\xa7ar excepcions retornant \xc3\xa8xit o fallada en un tipus Either permetent-ne l\'an\xc3\xa0lisi per casos. (Either tipError) implementa una m\xc3\xb2nada amb efecte fallada. (Left error) \xc3\xa9s l\'element absorbent per l\'esquerra de Either en (>>=). Aix\xc3\xb2 permet encadenar amb (>>=) diversos efectes que poden fallar obtenint l\'error del primer que falla._NEWLINE_-- prova.hsimport Control.Exception (try, evaluate, ArithException)import Data.Fixed (Uni, Deci, Centi, Milli, Micro, Nano, Pico) -- coma fixa de representaci\xc3\xb3 sencera--                                                        (sencer * resoluci\xc3\xb3_del_tipus)-- try :: Exception e => IO a -> IO (Either e a)type TipDada = Micro -- coma fixa, proveu tamb\xc3\xa9 TipDada = Doublemain = do_NEWLINE_         let x = 0.0001 :: TipDada_NEWLINE_             y = 0 :: TipDada_NEWLINE_         -- \'\'evaluate\'\' avalua com a efecte IO una expr. funcional que pot llan\xc3\xa7ar excepcions  _NEWLINE_         result <- try (evaluate (x/y)) :: IO (Either ArithException TipDada)_NEWLINE_         case result of_NEWLINE_             Right valor -> putStrLn $ "correcte: " ++ show valor_NEWLINE_             Left excep -> putStrLn $ "excepci\xc3\xb3: " ++ show excep_NEWLINE_Amb TipDada == Micro (Coma fixa) l\'excepci\xc3\xb3 salta_NEWLINE_excepci\xc3\xb3: divide by zero_NEWLINE_Amb TipDada == Double (Coma flotant IEEE 754), no hi ha excepci\xc3\xb3 (Divisi\xc3\xb3 entre zero), d\xc3\xb3na:_NEWLINE_correcte: Infinity_NEWLINE_try tamb\xc3\xa9 es pot fer servir amb finally, per\xc3\xb2 bracket \xc3\xa9s m\xc3\xa9s adequat per la gesti\xc3\xb3 de recursos.\n_START_SECTION_\ntry generalitzat\n_START_PARAGRAPH_\nDel paquet exceptions, generalitzant el context de llan\xc3\xa7ament i ca\xc3\xa7a d\'excepcions per a m\xc3\xb2nades diferents de l\'IO (aquelles que implementin MonadCatch)_NEWLINE_try :: (MonadCatch efecte, Exception ex) => efecte a -> efecte (Either ex a)\n_START_SECTION_\nobtenci\xc3\xb3 del punt de crida origen de la violaci\xc3\xb3 de la precondici\xc3\xb3\n_START_PARAGRAPH_\n1. Amb par\xc3\xa0metre impl\xc3\xadcit especial de tipus CallStack_NEWLINE_Vegeu ref. (Des de GHC 7.10.2) La seva obtenci\xc3\xb3 reflecteix la pila d\'aquelles crides on expl\xc3\xadcitament aparegui l\'impl\xc3\xadcit de tipus CallStack com a restricci\xc3\xb3 de context, amb el mateix nom de variable._NEWLINE_Des de GHC 8.0 vindr\xc3\xa0 definit un sin\xc3\xb2nim de restricci\xc3\xb3 HasCallStack que evitar\xc3\xa0 la necessitat de l\'extensi\xc3\xb3 de sintaxi ImplicitParams._NEWLINE_type HasCallStack = (?callStack :: CallStack) :: Constraint       -- especifica Constraint com a \'kind\' (tipus del tipus)_NEWLINE_Exemple:_NEWLINE_{-# LANGUAGE CPP #-} -- a les directives CPP els comentaris segueixen la sintaxi del C: /* comentari */#if MIN_VERSION_base(4,9,0)     /* GHC >= 8.0 */import Control.Exception (assert)import GHC.Stack (HasCallStack)funci\xc3\xb3Parcial :: HasCallStack => a -> b -> cfunci\xc3\xb3Parcial p1 p2 _NEWLINE_     | precondici\xc3\xb3 p1 p2 = {- cas definit -} assert (postcondici\xc3\xb3 p1 p2 resultat) resultat_NEWLINE_     | otherwise         = {- cas no definit -} error $ _NEWLINE_                             "funci\xc3\xb3Parcial: la precondici\xc3\xb3 falla" -- a GHC 8.0 hi ha bolcat autom\xc3\xa0tic del CallStack "?callStack" amb l\'error_NEWLINE_     -- la funci\xc3\xb3 \'error\' antiga (anterior a GHC 8.0) ha estat reanomenada \'errorWithoutCallStack\' al paquet \'base\'_NEWLINE_  where_NEWLINE_    resultat = expressi\xc3\xb3 p1 p2#elif MIN_VERSION_base(4,8,1)     /* GHC >= 7.10.2 && < 8.0 */{-# LANGUAGE ImplicitParams #-}import Control.Exception (assert)import GHC.Stack (CallStack, showCallStack)    _NEWLINE__NEWLINE_funci\xc3\xb3Parcial :: (?loc :: CallStack) => a -> b -> cfunci\xc3\xb3Parcial p1 p2 _NEWLINE_     | precondici\xc3\xb3 p1 p2 = {- cas definit -} assert (postcondici\xc3\xb3 p1 p2 resultat) resultat_NEWLINE_     | otherwise         = {- cas no definit -} error $ _NEWLINE_                             "funci\xc3\xb3Parcial: la precondici\xc3\xb3 falla; cridat des de : \\n" ++ showCallStack ?loc_NEWLINE_  where_NEWLINE_    resultat = expressi\xc3\xb3 p1 p2#endif_NEWLINE_2. Alternativa. Bolcar la pila de crides simulada, havent compilat amb la variant d\'ajustatge del RunTimeSystem. (profiling)_NEWLINE_La comprovaci\xc3\xb3 de la precondici\xc3\xb3 dins la rutina no ens informar\xc3\xa0 de la rutina origen del problema, excepte si habilitem la simulaci\xc3\xb3 de pila de crides de l\'ajustatge (compilant amb -prof i executant amb +RTS -xc). Vegeu  Depuraci\xc3\xb3. El problema de la manca d\'informaci\xc3\xb3 de situaci\xc3\xb3 en les petades\n_START_SECTION_\nNo finalitzaci\xc3\xb3 - S\xc3\xadmbol \xe2\x8a\xa5 (Bottom)\n_START_PARAGRAPH_\nValor intern que atura el programa prematurament indicant "No finalitzaci\xc3\xb3 del programa", especialment com a opci\xc3\xb3 de fons en un case, en cas que no encaixi cap de les opcions o b\xc3\xa9 un bucle sens fi. El tipus de \xe2\x8a\xa5 \xc3\xa9s arbitrari._NEWLINE_Prelude> :type error "abc"error "abc" :: t   -- el tipus de "no finalitzaci\xc3\xb3" \xc3\xa9s arbitrari._NEWLINE_En angl\xc3\xa8s bottom com a verb vol dir "tocar fons". En catal\xc3\xa0 es podria anomenar "fondeig" (fondejar: immobilitzar una barca, ancorant-la al fons).\n_START_SECTION_\nImplementaci\xc3\xb3 pendent - Undefined\n_START_PARAGRAPH_\nundefined \xc3\xa9s un valor de fondeig (\xe2\x8a\xa5: atura el programa) per poder explicitar el tipus d\'una funci\xc3\xb3 pendent d\'implementar i poder aix\xc3\xad passar la compilaci\xc3\xb3. Crida a la funci\xc3\xb3 error._NEWLINE_-- \'\'undefined\'\' en una definici\xc3\xb3, explicita implementaci\xc3\xb3 pendent_NEWLINE_ <identificador> <patrons> = undefined :: <tipus>\n_START_SECTION_\nVariables d\'estat global no sincronitzades IORef\n_START_PARAGRAPH_\nLes refer\xc3\xa8ncies IORef, equivalents de les ref del ML Est\xc3\xa0ndard, permeten modificar l\'estat global caracteritzat com a efecte IO._NEWLINE_No \xc3\xa9s convenient utilitzar una mateixa IORef en diferents fils d\'execuci\xc3\xb3. Protegir-ne m\xc3\xa9s d\'una mitjan\xc3\xa7ant atomicModifyIORef est\xc3\xa0 desaconsellat (les MVar hi s\xc3\xb3n m\xc3\xa9s indicades)._NEWLINE_ import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef)_NEWLINE_ import qualified Control.Monad as Monad_NEWLINE_ import System.IO (stdout, hFlush)_NEWLINE__NEWLINE_ tornem_hi :: IORef Bool -> IO ()_NEWLINE_ tornem_hi ref_estat = do_NEWLINE__NEWLINE_     x <- readIORef ref_estat     -- llegeix variable ref_estat_NEWLINE_     writeIORef ref_estat $ not x   -- escriu_NEWLINE__NEWLINE_     -- modifyIORef ref_estat (not)  -- alternativa: modifica la ref. amb la funci\xc3\xb3_NEWLINE__NEWLINE_     putStrLn $ _NEWLINE_       if x then "Blanc" else "Negre"_NEWLINE__NEWLINE_     putStr "Premeu intro:"_NEWLINE_     hFlush stdout_NEWLINE_     getLine     -- espera tecleig Intro i ignora el resultat del getLine_NEWLINE_                 -- sense variable (v <- getline),_NEWLINE_                 --    el bloc do compon les l\xc3\xadnies amb (>>) en lloc de (>>=)_NEWLINE_     return ()_NEWLINE__NEWLINE_ main = do_NEWLINE_     ref_estat <- newIORef False    -- crea variable del tipus del valor inicial_NEWLINE_                      --  i n\'obt\xc3\xa9 la refer\xc3\xa8ncia_NEWLINE_     Monad.forever $ tornem_hi ref_estat  -- repeteix seq\xc3\xbcencialment\n_START_SECTION_\nVariables d\'\xc3\xa0mbit local STRef per l\'encapsulament d\'efectes col\xc2\xb7laterals\n_START_PARAGRAPH_\nLa m\xc3\xb2nada ST (abbrev. de State) encapsula canvis d\'estat dins de codi funcional pur i permet fer computacions amb actualitzacions in situ (destructives) mitjan\xc3\xa7ant refer\xc3\xa8ncies STRef a objectes de cicle de vida restringit a l\'\xc3\xa0mbit i avaluaci\xc3\xb3 de l\'efecte.\n_START_SECTION_\nVariables MVar per a l\'acc\xc3\xa9s sincronitzat\n_START_PARAGRAPH_\nLes variables MVar ofereixen l\'acc\xc3\xa9s sincronitzat entre fils d\'execuci\xc3\xb3 amb el mecanisme de les b\xc3\xbasties de comunicaci\xc3\xb3. Ampliaci\xc3\xb3 a Haskell concurrent\n_START_SECTION_\nMutabilitat als vectors\n_START_PARAGRAPH_\nVegeu vectors d\'elements d\'allotjament directe\n_START_SECTION_\nfallada mon\xc3\xa0dica en el codi funcional\n_START_PARAGRAPH_\nCom acabem d\'esmentar, l\'element absorbent en l\'encadenament en la m\xc3\xb2nada Maybe (o b\xc3\xa9 Either) evita l\'avaluaci\xc3\xb3 de les computacions posteriors._NEWLINE_{-| fitxer total.hs-}{-# LANGUAGE UnicodeSyntax #-}headMay :: [a] \xe2\x86\x92 Maybe aheadMay (x : _) = return x  -- resultat exit\xc3\xb3s, equival a (Just x)headMay [] = Nothing        -- element absorbent de la m\xc3\xb2nada Maybe: (Nothing >>= _ = Nothing)doblar :: Num a => a \xe2\x86\x92 Maybe adoblar x = return $ 2 * xdoblarElCap :: Num a => [a] \xe2\x86\x92 Maybe adoblarElCap llista = headMay llista >>= doblar_NEWLINE_prova:_NEWLINE_$ ghciPrelude> :load total.hs[1 of 1] Compiling Main             ( total.hs, interpreted )Ok, modules loaded: Main.*Main> doblarElCap []Nothing*Main> doblarElCap [1,2,3]Just 2\n_START_SECTION_\nun tipus espec\xc3\xadfic per al subdomini de casos definits\n_START_PARAGRAPH_\nI una funci\xc3\xb3 de validaci\xc3\xb3 dels casos definits:_NEWLINE_import Control.Category ((>>>))   -- composici\xc3\xb3 esq-dreta -- f >>> g = g. fimport Data.Function ((&))  -- aplic. cap enrere -- (&) = flip ($) -- infixl 1  -- desde GHC 7.10.1newtype TLlistaNoBuida a = LlistaNoBuida { obtenirLlista :: [a]} deriving (Eq, Ord, Show)-- Constructor:                LlistaNoBuida :: [a] -> TLlistaNoBuida a-- Inversa del constructor:    obtenirLlista :: TLlistaNoBuida a -> [a]validaLlistaNoBuida :: [a] -> Maybe (TLlistaNoBuida a)validaLlistaNoBuida xs @ (_ : _) = Just $ LlistaNoBuida xsvalidaLlistaNoBuida [] = Nothinghead :: TLlistaNoBuida a -> ahead = obtenirLlista >>> Prelude.head _NEWLINE__NEWLINE_------------------------------------- operant en la m\xc3\xb2nada Maybe:-- un resultat Nothing (element absorbent en (>>=)) fa que l\'encadenament no progressi--obtenirLaLlistaNoBuidaMenor :: Ord a => [a] -> [a] -> Maybe (TLlistaNoBuida a)obtenirLaLlistaNoBuidaMenor l1 l2 = do_NEWLINE_         nb1 <- validaLlistaNoBuida l1_NEWLINE_         nb2 <- validaLlistaNoBuida l2_NEWLINE_         if nb1 < nb2 then return nb1 else return nb2default (Int) -- desambiguaci\xc3\xb3 dels literals num\xc3\xa8rics segons seq\xc3\xbc\xc3\xa8ncia de tipusmain = do_NEWLINE_         case obtenirLaLlistaNoBuidaMenor [1,2,3] [2,3,4] of_NEWLINE_           Just llistaNoBuida -> llistaNoBuida & show & putStrLn_NEWLINE_           Nothing -> putStrLn "alguna de les llistes era buida"\n_START_SECTION_\nfallada mon\xc3\xa0dica en els efectes col\xc2\xb7laterals - el transformadors EitherT i MaybeT\n_START_PARAGRAPH_\nLa fallada en la m\xc3\xb2nada IO per encaixos incomplets del segon operand de (>>=) (op. fail despla\xc3\xa7ada (des de GHC 8.0) a la classe MonadFail) es produeix disparant una excepci\xc3\xb3 IOError._NEWLINE_En el cas de la m\xc3\xb2nada ST, el comportament no est\xc3\xa0 definit. La implementaci\xc3\xb3 per defecte crida la rutina error aturant el programa._NEWLINE_Per afegir-hi la funcionalitat de l\'element absorbent en (>>=) cal aplicar-hi un transformador de m\xc3\xb2nades que la incorpori._NEWLINE_El transformador de m\xc3\xb2nades EitherT, de manera similar al MaybeT, afegeix la possibilitat d\'evitar c\xc3\xa0lculs posteriors a la fallada, a una m\xc3\xb2nada, afegint-hi a m\xc3\xa9s a m\xc3\xa9s, informaci\xc3\xb3 de l\'error. Aqu\xc3\xad  l\'aplicarem a la m\xc3\xb2nada IO, resultant la m\xc3\xb2nada (EitherT tipError IO)._NEWLINE_{-# LANGUAGE PackageImports, UnicodeSyntax #-}import "either" Control.Monad.Trans.Either (EitherT (..))import "transformers" Control.Monad.Trans.Class (lift)import Control.Category ((>>>))                       -- g >>> f == f. g-- el tipus EitherT, definit a Control.Monad.Trans.Either-- newtype EitherT err m\xc3\xb2nada a = EitherT { runEitherT :: m\xc3\xb2nada (Either err a) }-- els valors (Left err) s\xc3\xb3n elements absorbents de la m\xc3\xb2nada Either en (>>=)-- errors de l\'aplicaci\xc3\xb3data Err = ErrLectura | ErrForaMarges Int deriving (Eq)instance Show Err where_NEWLINE_  show ErrLectura = "error de lectura"_NEWLINE_  show (ErrForaMarges x) = "fora marges: " ++ show x-- funci\xc3\xb3 total -- en comptes d\'excepci\xc3\xb3 retorna fallada amb l\'errorllegirSencer :: String \xe2\x86\x92 Either Err IntllegirSencer s = case reads s of_NEWLINE_    [(x, "")] \xe2\x86\x92 return x_NEWLINE_    _         \xe2\x86\x92 Left ErrLectura     -- element absorbentllegeixSencerDEntrada :: EitherT Err IO IntllegeixSencerDEntrada = do_NEWLINE_                        s <- lift getLine_NEWLINE_                        EitherT $ return $ llegirSencer s-- apliquem encadenaments sobre el resultat de la lectura, segurs que no petar\xc3\xa0.comprovaMarges :: Int \xe2\x86\x92 EitherT Err IO IntcomprovaMarges x = if x >= 0_NEWLINE_                      then return x_NEWLINE_                      else EitherT $ return $ Left $ ErrForaMarges x   -- element absorbentobtenirLArrelQuadrada :: Int \xe2\x86\x92 EitherT err IO FloatobtenirLArrelQuadrada = fromIntegral >>> sqrt >>> returnmain = do_NEWLINE_        -- en l\'encadenament (>>=) el primer resultat Left (element absorbent en (>>=)) fa que l\'avaluaci\xc3\xb3 no progressi._NEWLINE_        eiResult <- runEitherT $ llegeixSencerDEntrada >>= comprovaMarges >>= obtenirLArrelQuadrada_NEWLINE_        case eiResult of_NEWLINE_             Right v \xe2\x86\x92 putStrLn $ "resultat: " ++ show v_NEWLINE_             Left err \xe2\x86\x92 putStrLn $ "error: " ++ show err     -- mostra el primer error que es produeixi_NEWLINE_cabal install either_NEWLINE_runhaskell prova.hs\n_START_SECTION_\nPrisma\n_START_PARAGRAPH_\nUn prisma \xc3\xa9s una lent per enfocar un component d\'un tipus suma (pluri-constructor), que pot no ser present en un valor i per tant fallar._NEWLINE_-- Sigui \'a\' el tipus del component objectiu de l\'estructura d\'entrada de tipus \'ta\'-- i \'b\' el tipus del component transformat, pertanyent a l\'estructura de sortida de tipus \'tb\'_NEWLINE_La funci\xc3\xb3 de selecci\xc3\xb3, primer par\xc3\xa0metre del generador prism, ofereix en un tipus Either el component enfocat o b\xc3\xa9, 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)._NEWLINE_El segon par\xc3\xa0metre del generador prism construeix l\'estructura resultant partint de la imatge del component enfocat (b -> tb)._NEWLINE_Exemple amb el cap en una llista._NEWLINE_-- de Mezzolens.Optics substituint l\'\xc3\xa0lies Opticaltype Prism ta tb a b = forall p. Choice p => p a b -> p ta tb  _NEWLINE__NEWLINE_-- Choice \xc3\xa9s una especialitat de Profunctor amb lents que permeten transformar un tipus Either en funci\xc3\xb3 de la transformaci\xc3\xb3 d\'un component.class Profunctor p => Choice p where_NEWLINE_  _Left :: p a b -> p (Either a c) (Either b c)        -- lent sobre el component de la variant Left_NEWLINE_  _Right :: p a b -> p (Either c a) (Either c b)       -- lent sobre el component de la variant Right-- de Mezzolens.Uncheckedprism :: (ta -> Either tb a) -> (b -> tb) -> Prism ta tb a b-- ^ prism match build--   match proporciona el component amb Right o b\xc3\xa9 l\'estructura resultant buida amb Left --   build forma una variant de l\'estructura resultant multi-constructor, partint de la imatge del component_NEWLINE_ _NEWLINE_*Main> import Mezzolens as M*Main M> import Mezzolens.Unchecked as MU*Main M MU> :set -XLambdaCase-- prisma sobre el cap d\'una llista*Main M MU> :{ -- getter parcial oferint el resultat en un Either_NEWLINE_               let headMatch :: [a] -> Either [a] a _NEWLINE_                   headMatch = \\case  _NEWLINE_                          (x : _) -> Right x  -- resultat per a variant objectiu_NEWLINE_                          [] -> Left []     -- resultat per a variant no objectiu  _NEWLINE_ _NEWLINE_                   headBuild = \\x -> [x]_NEWLINE__NEWLINE_               let _Cap = MU.prism headMatch headBuild_NEWLINE_            :}-- Consulta amb el prisma*Main M MU> [sitBcn] ^? (_Cap. lentGrausDeLatitud)  -- (^?) ofereix el resultat del \'getter\' parcial en un MaybeJust 41-- Actualitzaci\xc3\xb3 sobre estructura que cont\xc3\xa9 la variant objectiu del prisma*Main M MU> [sitBcn] & (_Cap. lentGrausDeLatitud) (+2)[Situaci\xc3\xb3 {_latitud = Arc {_graus = 43, _minuts = 23, _segons = 57}, _longitud = Arc {_graus = 2, _minuts = 7, _segons = 40}}]-- Actualitzaci\xc3\xb3 sobre estructura que no cont\xc3\xa9 la variant objectiu                      *Main M MU> [] & (_Cap. lentGrausDeLatitud) (+2)[]\n_START_SECTION_\nencapsulament\n_START_PARAGRAPH_\nNo hi ha doble especificaci\xc3\xb3 (interf\xc3\xadcie / implementaci\xc3\xb3) per als m\xc3\xb2duls._NEWLINE_S\'exporten els identificadors llistats a la cl\xc3\xa0usula module, o tots si no hi ha llista._NEWLINE_module A(_NEWLINE_  func1, Tipus2, Classe3,_NEWLINE_  pattern Sin\xc3\xb2nimDePatr\xc3\xb3,     -- amb l\'extensi\xc3\xb3 de llenguatge \'PatternSynonyms\'_NEWLINE_  module M\xc3\xb2dulP, {- reexporta tot el que s\'importa d\'aquest m\xc3\xb2dul -}_NEWLINE_  module M\xc3\xb2dulX, {- cas d\'un \xc3\xa0lies, reexporta tot el que s\'importa dels m\xc3\xb2duls reanomenats -}_NEWLINE_  module A {- si el nom del m\xc3\xb2dul coincideix amb l\'actual, exporta totes les declaracions locals -}_NEWLINE_  ) whereimport M\xc3\xb2dulP (A,B,C)       -- detalla elements a importar que re-exportarem citant el m\xc3\xb2dul-- el mateix \xc3\xa0lies permet reexportar el contingut de diversos m\xc3\xb2duls de copimport M\xc3\xb2dulQ as M\xc3\xb2dulXimport M\xc3\xb2dulR as M\xc3\xb2dulXimport M\xc3\xb2dulS as M\xc3\xb2dulX...\n_START_SECTION_\ndistingir entre tipus i valors a l\'export./import. quan hi ha coincid\xc3\xa8ncies\n_START_PARAGRAPH_\nPer exportar operadors constructors de tipus i no confondre\'ls amb un operador funci\xc3\xb3 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\xc3\xa9 importar. Cal esmentar l\'extensi\xc3\xb3 de llenguatge ExplicitNamespaces o altres que la impliquin._NEWLINE_{-# LANGUAGE ExplicitNamespaces #-}module N( -- \'type\' a l\'exportaci\xc3\xb3 explicita l\'espai de noms de l\'identificador que segueix_NEWLINE_  f, _NEWLINE_  type (++)    -- amb \'type\' exporta el constructor de tipus (++) definit tot seguit_NEWLINE_               -- evitant la confusi\xc3\xb3 amb la funci\xc3\xb3 (++) de les llistes) where     _NEWLINE_    data family a ++ b = L a | R b-- per reexportar-lomodule M( f, type (++) ) where ..._NEWLINE_    import N( f, type (++) )\n_START_SECTION_\nImportaci\xc3\xb3\n_START_PARAGRAPH_\nimport M\xc3\xb2dulA -- importa-ho tot_NEWLINE_ import M\xc3\xb2dulA (id1, id2, id3)  -- enumeraci\xc3\xb3: importa nom\xc3\xa9s els esmentats_NEWLINE_ import M\xc3\xb2dulA hiding (id1, id2) -- \'\'hiding\'\': tots excepte els esmentats_NEWLINE_ -- as B: reanomenament del m\xc3\xb2dul_NEWLINE_ import qualified M\xc3\xb2dulB as B  -- \'\'qualified\'\': qualificaci\xc3\xb3 obligat\xc3\xb2ria: B.ident_NEWLINE_ import M\xc3\xb2dulB as B [hiding (...] -- sense \'\'qualified\'\': qualificaci\xc3\xb3 opcional en cas de col\xc2\xb7lisi\xc3\xb3 de noms_NEWLINE_ import M\xc3\xb2dulA as B (id1, id2)  -- importa els esmentats amb qualificaci\xc3\xb3 opcional reanomenada\n_START_SECTION_\nImportacions especificant el paquet desitjat\n_START_PARAGRAPH_\nCal esmentar la pragma d\'ampliaci\xc3\xb3 de sintaxi {-# LANGUAGE PackageImports #-}_NEWLINE_import "nom_del_paquet" Nom_del_m\xc3\xb2dul-- com ara:import "network" Network.Socketimport qualified "network" Network.Socket as NS\n_START_SECTION_\nEvitar la importaci\xc3\xb3 autom\xc3\xa0tica de les funcions predefinides\n_START_PARAGRAPH_\nPer evitar-ne la importaci\xc3\xb3 de nom\xc3\xa9s algunes:_NEWLINE_import Prelude hiding (head, tail, init, last) -- amaga funcions parcials del \'Prelude\' que poden petar (n\'hi ha una colla)_NEWLINE_Amb la pragma {-# LANGUAGE NoImplicitPrelude #-} amaguem tot el Prelude, i podem substituir-lo per un altre m\xc3\xb2dul:_NEWLINE_-- Per a l\'exemple que substitueix l\'entrada/sortida de tipus String per la de tipus Text-- perqu\xc3\xa8 els car\xc3\xa0cters no anglosaxons ([[ASCII]]), el tipus String els mostra amb codis num\xc3\xa8rics.module ElMeuPrelude (_NEWLINE_  putStr, putStrLn, getLine_NEWLINE_  module PreludeMancat,        -- exporta la resta del Prelude de \'PreludeMancat\') whereimport Prelude as PreludeMancat hiding (putStr, putStrLn, getLine)  -- amaga la E/S amb operands Stringimport Data.Text.IO (putStr, putStrLn, getLine)                     -- importa la E/S per al tipus Text_NEWLINE_\xc3\xbas:_NEWLINE_-- no importis el Prelude que ja tinc el meu.{-# LANGUAGE NoImplicitPrelude #-}module ... whereimport ElMeuPrelude...\n_START_SECTION_\nespai de noms de m\xc3\xb2dul jer\xc3\xa0rquic\n_START_PARAGRAPH_\nEls detalls de tractament intern que no formaran part de l\'API se solen encapsular en m\xc3\xb2duls allotjats en carpetes internes. Per accedir-hi, un nom del m\xc3\xb2dul separat per punts ("A.B.NomDelFitxer") reflecteix el cam\xc3\xad d\'acc\xc3\xa9s (A/B/NomDelFitxer), excepte l\'extensi\xc3\xb3 del fitxer, que indica si el font \xc3\xa9s de codi (.hs) o \xc3\xa9s un document al qual cal aplicar un preprocessador (de l\xc3\xa8xic (.x), de gram\xc3\xa0tica (.y), de programaci\xc3\xb3 liter\xc3\xa0ria (incrustada dins la documentaci\xc3\xb3) (.lhs), o altres) per obtenir-ne el codi font._NEWLINE_En compilar, el senyal -i<dirs> indica a GHC la llista de directoris base de la recerca dels fonts_NEWLINE_\xc3\x89s corrent reanomenar els noms jer\xc3\xa0rquics a un sobrenom curt_NEWLINE_ import qualified Control.Monad.ST.Strict as ST\n_START_SECTION_\nm\xc3\xb2duls amb refer\xc3\xa8ncies m\xc3\xbatues (m\xc3\xbatuament recursius)\n_START_PARAGRAPH_\nVegeu-ho a Compilador Haskell de Glasgow#M\xc3\xb2duls amb refer\xc3\xa8ncies m\xc3\xbatues (m\xc3\xbatuament recursius)\n_START_SECTION_\narrencada\n_START_PARAGRAPH_\nEl m\xc3\xb2dul principal ha de dur per nom de m\xc3\xb2dul "Main" i ha d\'exportar la funci\xc3\xb3 "main". Si no hi ha cl\xc3\xa0usula module es pren per defecte "module Main where", exportant tots els identificadors (\xc3\xbatil per a proves a l\'int\xc3\xa8rpret)._NEWLINE_Els arguments de la l\xc3\xadnia d\'ordres de consola (getArgs), no inclouen el nom del programa, que s\'obt\xc3\xa9 amb getProgName._NEWLINE_Per indicar l\'eixida amb codi de finalitzaci\xc3\xb3: exitWith (ExitSuccess | ExitFailure codi_de_finalitzaci\xc3\xb3) dispara una excepci\xc3\xb3 de fi de programa._NEWLINE_Exemple senzill. (System.Environment no t\xc3\xa9 en compte la codif. local, vegeu comentari):_NEWLINE_-- per una lectura correcta (dels car\xc3\xa0cters no anglosaxons) de la consola de comandes a Linux--  cal esmentar "System.Environment.UTF8" del paquet utf8-string--, en lloc de "System.Environment"import System.Environment (getProgName, getArgs)   -- a Linux System.Environment.UTF8import System.Exit (exitSuccess, exitWith, ExitCode(..))import Text.Printf (printf)main = do_NEWLINE_         args <- getArgs_NEWLINE_         nomProg <- getProgName_NEWLINE_         case args of_NEWLINE_            [] -> do_NEWLINE_                    printf "%s: cal especificar un par\xc3\xa0metre.\\n" nomProg_NEWLINE_                    exitWith (ExitFailure 1)    -- dispara excep. de fi de programa especificant el codi de finalitzaci\xc3\xb3._NEWLINE__NEWLINE_            (arg:_) -> do_NEWLINE_                         printf "el primer param. \xc3\xa9s: %s\\n" arg_NEWLINE_                         exitSuccess     -- equival a: exitWith ExitSuccess -- dispara excep. de fi de programa amb codi 0_NEWLINE_En el llan\xc3\xa7ament, a m\xc3\xa9s dels par\xc3\xa0metres del programa, s\'hi poden afegir par\xc3\xa0metres per al Run Time System a partir del separador +RTS tancant opcionalment amb -RTS en cas d\'haver d\'afegir, tot seguit, par\xc3\xa0metres pel programa\n_START_SECTION_\narrencada amb opcions\n_START_PARAGRAPH_\nVegeu-ho a GHC.\n_START_SECTION_\nfuncions i tipus predefinits i biblioteques b\xc3\xa0siques\n_START_PARAGRAPH_\nEl m\xc3\xb2dul de funcions predefinides es coneix com a "Prelude". Vegeu Prelude est\xc3\xa0ndard. Prelude del GHC._NEWLINE_Les API\'s de les biblioteques b\xc3\xa0siques s\xc3\xb3n aqu\xc3\xad_NEWLINE_Podeu consultar a quins m\xc3\xb2duls pot pert\xc3\xa0nyer un identificador mitjan\xc3\xa7ant els cercadors de l\'API del Haskell Hayoo o b\xc3\xa9 Hoogle\n_START_SECTION_\nPrecisi\xc3\xb3 dels tipus b\xc3\xa0sics\n_START_PARAGRAPH_\nVegeu-ho a GHC#Precisi\xc3\xb3 dels tipus b\xc3\xa0sics\n_START_SECTION_\namb actualitzaci\xc3\xb3 de c\xc3\xb2pia completa\n_START_PARAGRAPH_\nIneficients en espai. Vegeu Array UArray_NEWLINE_ data Array idx elem  -- Elements allotjats indirectament (encapsulats en mem\xc3\xb2ria din\xc3\xa0mica, avaluaci\xc3\xb3 tardana)_NEWLINE_ data UArray idx elem -- Amb U de \'\'Unboxed\'\': elements no encapsulats, allotjats directament, avaluaci\xc3\xb3 estricta._NEWLINE_-- exempleimport Data.Array.Unboxed (UArray)  -- UArray: tipus amb elements \'unboxed\' (no encapsulats)import Data.Array.IArray (listArray)  -- IArray: interf\xc3\xadcie immutablevec :: UArray Int Float  -- vector de Floats amb \xc3\xadndex de tipus Intvec = listArray (0,2) [0.5, 1.5, 2.5]-- (//) actualitzaci\xc3\xb3 amb una llista de parells (\xc3\xadndex, nou_valor)nouVec = vec // [(indx, nou_valor)]   -- c\xc3\xb2pia completa\n_START_SECTION_\nVectors immutables del H98\n_START_PARAGRAPH_\nLa classe Array combinada amb la Ix (\xc3\xadndexs), especificades en el Haskell98, implementen vectors immutables amb elements d\'avaluaci\xc3\xb3 tardana._NEWLINE_ -- vector d\'una dimensi\xc3\xb3, s\'inicialitza amb_NEWLINE_ --      el rang i una llista exhaustiva de parells (\xc3\xadndex, valor)_NEWLINE_ import Data.Array        -- Array al Haskell98_NEWLINE__NEWLINE_ vec = array (menor, major) [ (i, expr_valor) | i <-[ menor..major ]]_NEWLINE_ element = vec!indx     -- (!) valor per a l\'\xc3\xadndex indx_NEWLINE__NEWLINE_ -- (//) actualitzaci\xc3\xb3 amb una llista de parells (\xc3\xadndex, nou_valor)_NEWLINE_ nouVec = vec // [(indx, nou_valor)]_NEWLINE__NEWLINE_ -- vector de dues dimensions_NEWLINE_ w = array ((menor_i1, menor_i2), (major_i1, major_i2)) [( (i, j), expr_valor) |_NEWLINE_        i <- [menor_i1..major_i1], j <- [menor_i2..major_i2]]\n_START_SECTION_\nvector amb \xc3\xadndex de tipus enumerat\n_START_PARAGRAPH_\nCaldr\xc3\xa0 que l\'enumerat implementi la classe dels \xc3\xadndexs Ix (A GHC: al m\xc3\xb2dul Data.Ix)_NEWLINE_class Ord a => Ix a where_NEWLINE_  range :: (a, a) -> [a]          -- \'(range (desDe, finsA))\' obt\xc3\xa9 la llista [desDe .. finsA]_NEWLINE_  index :: (a, a) -> a -> Int     -- \'(\xc3\xadndex (desDe, finsA) x)\' obt\xc3\xa9 la dist\xc3\xa0ncia( desDe, x)_NEWLINE_  inRange :: (a, a) -> a -> Bool  -- \'(inRange (desDe, finsA) x)\' indica si (desDe <= x && x <= finsA)_NEWLINE_  rangeSize :: (a, a) -> Int      -- \'(rangeSize (desDe, finsA))\' obt\xc3\xa9 la mida de [desDe .. finsA]_NEWLINE_Exemple:_NEWLINE_ import Data.Array       -- Array al Haskell98 _NEWLINE_ import Data.Ix          -- Ix al Haskell98_NEWLINE_ import Text.Printf_NEWLINE_ import Data.Function ((&))  -- (&) = flip ($) -- infixl 1  -- desde GHC 7.10.1_NEWLINE__NEWLINE_ data DiaFeiner = Dl | Dm | Dc | Dj | Dv_NEWLINE_          deriving (Show, Eq, Ord, Enum, Ix) -- el compilador instancia Ix_NEWLINE__NEWLINE_ enc\xc3\xa0rrecs :: Array DiaFeiner Int_NEWLINE_ enc\xc3\xa0rrecs = array (Dl,Dv) [(Dl,5),(Dm,6),(Dc,3),(Dj,7),(Dv,8)]  -- rang i parells (\xc3\xadndex, valor)_NEWLINE__NEWLINE_ main = do_NEWLINE_     printf "Per dimecres tinc %d enc\xc3\xa0rrecs\\n" (enc\xc3\xa0rrecs!Dc)_NEWLINE__NEWLINE_     putStr "De Dilluns a Divendres: "_NEWLINE_     range (Dl,Dv) & map (enc\xc3\xa0rrecs!) -- aplicaci\xc3\xb3 parcial de l\'operaci\xc3\xb3 (!)_NEWLINE_                   & show_NEWLINE_                   & putStrLn_NEWLINE_A part d\'aquests vectors, que generen una c\xc3\xb2pia a cada actualitzaci\xc3\xb3, n\'hi ha d\'altres de for\xc3\xa7a m\xc3\xa9s eficients. Entre aquests vegeu m\xc3\xa9s avall #Vectors mudables de dades no encapsulades.\n_START_SECTION_\nVectors mudables de dades no encapsulades\n_START_PARAGRAPH_\nAmb allotjament directe (no encapsulat) dels elements.\n_START_SECTION_\nEstructures TAD gen\xc3\xa8riques\n_START_PARAGRAPH_\nL\'equivalent dels m\xc3\xb2duls gen\xc3\xa8rics (param\xc3\xa8trics en tipus) d\'altres llenguatges, es concreta o b\xc3\xa9 afegint-los com a par\xc3\xa0metres de la classe, o b\xc3\xa9 amb tipus associats a la classe.\n_START_SECTION_\nGen\xc3\xa8rics amb classes multi-par\xc3\xa0metre i depend\xc3\xa8ncies funcionals\n_START_PARAGRAPH_\nAfegint les variables de tipus com a par\xc3\xa0metres de les classes i definint-ne les relacions amb depend\xc3\xa8ncies funcionals._NEWLINE_A les classes multipar\xc3\xa0metre pot ser que una part dels par\xc3\xa0metres vingui determinada per altres (per exemple el tipus de la col\xc2\xb7lecci\xc3\xb3 determina el tipus de l\'element)._NEWLINE_La sintaxi de les depend\xc3\xa8ncies funcionals \xc3\xa9s:_NEWLINE_class NomClasse a b c | a b -> c where_NEWLINE_indicant que a les inst\xc3\xa0ncies el grup de valors (a, b) determina el de  \'c\'  i n\'ha d\'esperar una sola inst\xc3\xa0ncia per cada ocurr\xc3\xa8ncia del grup determinador. Els tipus determinats s\'expressen en funci\xc3\xb3 dels determinadors, i si s\xc3\xb3n monom\xc3\xb2rfics (sense variables) n\'hi ha prou amb el comod\xc3\xad \'_\'._NEWLINE_-- exemple de classe multi-param. amb depend\xc3\xa8ncies funcionals{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}class (Eq elt) => Conjunt cjt elt | cjt -> elt where_NEWLINE_  buit :: cjt_NEWLINE_  afegeix :: elt -> cjt -> cjtinstance Eq a => Conjunt [a] a where_NEWLINE_  buit = []_NEWLINE_  afegeix x [] = [x]_NEWLINE_  afegeix x (y : ys)_NEWLINE_            | x == y = y : ys_NEWLINE_            | otherwise = y : afegeix x ystest = afegeix 1 $ (buit :: [Int])main = print test\n_START_SECTION_\nMonomorfisme, polimorfisme i quantificadors expl\xc3\xadcits\n_START_PARAGRAPH_\nVegeu ref.\n_START_SECTION_\nVariables d\'acc\xc3\xa9s no garantit (amb unsafePerformIO)\n_START_PARAGRAPH_\n\xc3\x89s una soluci\xc3\xb3 poc ortodoxa per la modificaci\xc3\xb3 de variables globals sense haver de passar la variable com a par\xc3\xa0metre, b\xc3\xa0sicament per la modificaci\xc3\xb3 de prefer\xc3\xa8ncies en temps d\'execuci\xc3\xb3._NEWLINE_De fet trenca el principi de transpar\xc3\xa8ncia referencial de les funcions que les incorporin: const\xc3\xa0ncia del resultat amb les mateixes entrades, impedint l\'\xc3\xbas de t\xc3\xa8cniques d\'optimitzaci\xc3\xb3 com la memo\xc3\xaftzaci\xc3\xb3 (taules par\xc3\xa0metres/resultats per evitar el rec\xc3\xa0lcul)._NEWLINE_Cal assegurar-se que la seva modificaci\xc3\xb3 sigui avaluada, abans de fer-ne \xc3\xbas, perqu\xc3\xa8 el llenguatge no ho garanteix._NEWLINE_unsafePerformIO \xc3\xa9s la "porta del darrere" de la m\xc3\xb2nada IO._NEWLINE_{-# OPTIONS_GHC -fno-cse -fno-full-laziness #-}  -- recomanaci\xc3\xb3 de System.IO.Unsafeimport System.IO.Unsafeimport Data.IORef-- variable de prova, a l\'estil del llenguatge ML{-# NOINLINE intRef #-} -- recomanaci\xc3\xb3 de System.IO.UnsafeintRef :: IORef IntintRef = unsafePerformIO $ newIORef 0-- amp par\xc3\xa0metre \'\'unit\'\' () per for\xc3\xa7ar el rec\xc3\xa0lcul a cada invocaci\xc3\xb3--   evitant la memoritzaci\xc3\xb3 de les definicions sense par\xc3\xa0metres{-# NOINLINE llegeix #-}llegeix :: () -> Intllegeix _ = unsafePerformIO $ readIORef intRef_NEWLINE_Aquesta soluci\xc3\xb3 \xc3\xa9s incompatible amb la certificaci\xc3\xb3 Safe Haskell._NEWLINE_El sistema m\xc3\xa9s correcte \xc3\xa9s tractar les prefer\xc3\xa8ncies com un entorn canviant i passar-lo com a par\xc3\xa0metre all\xc3\xa0 on calgui, fent servir la m\xc3\xb2nada Reader o b\xc3\xa9 el transformador de m\xc3\xb2nades corresponent ReaderT._NEWLINE_Vegeu Compilador Haskell de Glasgow#Tractament d\'un entorn canviant, amb la m\xc3\xb2nada Reader\n_START_SECTION_\nFam\xc3\xadlies de tipus\n_START_PARAGRAPH_\nS\xc3\xb3n una generalitzaci\xc3\xb3 dels tipus associats a les classes, i permeten la definici\xc3\xb3, a nivell de m\xc3\xb2dul, dels tipus dependents d\'un altre tipus, declarat com a \xc3\xadndex de la fam\xc3\xadlia, que en el cas dels tipus associats correspondria al tipus \xc3\xadndex de la classe._NEWLINE_L\'especificaci\xc3\xb3 equivalent a la signatura del tipus associat duu el qualificatiu family (com data family o b\xc3\xa9 type family) mentre que la corresponent a les inst\xc3\xa0ncies duen el qualificatiu instance com es detalla tot seguit.\n_START_SECTION_\nFam\xc3\xadlies de sin\xc3\xb2nims de tipus tancades\n_START_PARAGRAPH_\nUna fam\xc3\xadlia de sin\xc3\xb2nims de tipus amb un conjunt tancat (no ampliable) d\'inst\xc3\xa0ncies es pot expressar incloent les inst\xc3\xa0ncies de la fam\xc3\xadlia en una cl\xc3\xa0usula where._NEWLINE_type family F a where_NEWLINE_  F Int  = Double_NEWLINE_  F Bool = Char_NEWLINE_  F a    = String\n_START_SECTION_\ntipus dependents de valors\n_START_PARAGRAPH_\nVegeu ref. Exemple a Compilador_Haskell_de_Glasgow#Tipus_dependents_de_valors\n_START_SECTION_\ndefinici\xc3\xb3 t\xc3\xa0cita o point-free\n_START_PARAGRAPH_\nLa programaci\xc3\xb3 t\xc3\xa0cita o point-free (sense arguments) estalvia arguments en les definicions aplicant la reducci\xc3\xb3 eta del c\xc3\xa0lcul lambda._NEWLINE_-- definici\xc3\xb3arrelQuad x = sqrt x-- en forma de lambdaarrelQuad = \\x -> sqrt x _NEWLINE__NEWLINE_-- per la reducci\xc3\xb3 eta, at\xc3\xa8s que x no \xc3\xa9s una variable lliure de l\'expressi\xc3\xb3 (sqrt)arrelQuad = sqrt   -- versi\xc3\xb3 t\xc3\xa0cita o \'point-free\' (estalviant arguments)\n_START_SECTION_\nForma Normal\n_START_PARAGRAPH_\nUna expressi\xc3\xb3 est\xc3\xa0 en forma normal si no s\'hi poden aplicar m\xc3\xa9s reduccions. Est\xc3\xa0 completament avaluada (en profunditat)._NEWLINE_Una expressi\xc3\xb3 que comen\xc3\xa7a per un constructor est\xc3\xa0 en HNF, i aix\xc3\xb2 impedeix l\'avaluaci\xc3\xb3 de les expressions dels components (avaluant amb seq). Perqu\xc3\xa8 quedin avaluades, cal, o b\xc3\xa9 definir-les estrictes als tipus, o b\xc3\xa9 avaluar amb deepseq o l\'equivalent $!! a "forma normal"._NEWLINE_La classe NFData (contracci\xc3\xb3 de NormalFormData) del paquet deepseq (a partir de GHC 7.4.1 forma part del conjunt b\xc3\xa0sic de biblioteques de GHC) defineix la signatura d\'una funci\xc3\xb3 rnf (inicials de Reduce to Normal Form) per l\'avaluaci\xc3\xb3 en profunditat. Per crear una inst\xc3\xa0ncia de NFData per a un tipus algebraic, caldr\xc3\xa0 una implementaci\xc3\xb3 de rnf que apliqui recursivament rnf a les variables d\'encaix corresponents als components dels constructors._NEWLINE_-- la funci\xc3\xb3 \'\'rnf\'\' inicials de la traducci\xc3\xb3 anglesa de "Reducci\xc3\xb3 a Forma Normal"class NFData a where_NEWLINE_  rnf :: a -> ()   -- rnf ha d\'avaluar el par\xc3\xa0metre en profunditat a Forma Normal_NEWLINE_import Control.DeepSeqdata NomDelTipus = Cons1 T1 T2 | Cons2 T3instance NFData NomDelTipus where_NEWLINE_  rnf (Cons1 t1 t2) = (rnf t1) `seq` (rnf t2) `seq` ()_NEWLINE_  rnf (Cons2 t3) = (rnf t3) `seq` ()_NEWLINE_Automatitzable amb el travessament gen\xc3\xa8ric de les estructures algebraiques._NEWLINE_{-# LANGUAGE DeriveGeneric #-}import Control.DeepSeqimport Control.DeepSeq.Generics (genericRnf)import GHC.Genericsdata NomDelTipus = Cons1 T1 T2 | Cons2 T3 deriving Genericinstance NFData NomDelTipus where rnf = genericRnf\n_START_SECTION_\nAvaluaci\xc3\xb3 estricta expl\xc3\xadcita\n_START_PARAGRAPH_\nA part de l\'optimitzaci\xc3\xb3 en estrictesa dels compiladors (vegeu article "Haskell \xc3\xa9s un llenguatge estricte") es pot for\xc3\xa7ar l\'avaluaci\xc3\xb3 estricta de les seg\xc3\xbcents maneres:\n_START_SECTION_\nAplicaci\xc3\xb3 estricta (Crida per valor)\n_START_PARAGRAPH_\nAvaluaci\xc3\xb3 del par\xc3\xa0metre abans de la substituci\xc3\xb3 (c\xc3\xa0lcul lambda). Amb l\'operador d\'aplicaci\xc3\xb3 estricta ($!) com a alternativa de ($) d\'avaluaci\xc3\xb3 tardana. (seq) avalua el primer operand i retorna el segon. Al Haskell98 (seq) avaluava a HNF per\xc3\xb2 al Haskell2010 avalua a WHNF (posposa la reducci\xc3\xb3 de les lambdes i de les expressions dels constructors)._NEWLINE_ f $! x = x `seq` (f x)\n_START_SECTION_\nAplicaci\xc3\xb3 estricta a Forma Normal\n_START_PARAGRAPH_\n($!!) amb doble signe d\'exclamaci\xc3\xb3, avalua l\'operand en profunditat (amb deepseq) a Forma Normal, per als casos on l\'operand \xc3\xa9s un tipus que implementa la classe NFData. La generaci\xc3\xb3 d\'inst\xc3\xa0ncies de NFData per a tipus algebraics es pot fer amb mecanismes de derivaci\xc3\xb3 gen\xc3\xa8rica (amb recorregut gen\xc3\xa8ric dels tipus algebraics)._NEWLINE_import Control.DeepSeq-- ($!!) :: NFData a => (a -> b) -> a -> b     -- infixr 0 $!!f $!! x = x `deepseq` (f x)\n_START_SECTION_\nEstrictesa als par\xc3\xa0metres formals\n_START_PARAGRAPH_\nAvaluaci\xc3\xb3 estricta als par\xc3\xa0metres formals amb l\'extensi\xc3\xb3 {-# LANGUAGE BangPatterns #-}_NEWLINE_{-# LANGUAGE BangPatterns #-}f !x !y = 2 * x * y         -- avalua estrictament (!) els par\xc3\xa0metres actuals (a WHNF){-# LANGUAGE Strict #-}            -- des de GHC 8.0f x y = 2 * x * y       -- amb Strict avaluaci\xc3\xb3 estricta no-irrefutable per defecte, prefix (~) per l\'avaluaci\xc3\xb3 com abans\n_START_SECTION_\nfoldl\': iteracions amb plegat per l\'esquerra estricte\n_START_PARAGRAPH_\nl\'operaci\xc3\xb3 foldl (foldLeft) permet fer "transformacions reiterades sobre una estructura de tipus a amb els valors d\'una seq\xc3\xbc\xc3\xa8ncia [b] ((a -> b -> a)), de manera equivalent als bucles for|forEach de la prog. imperativa tradicional._NEWLINE_ foldl :: (a -> b -> a) -> a -> [b] -> a   -- essent \'\'a\'\' l\'estructura i \'\'[b]\'\' la llista de valors a iterar_NEWLINE_-- versi\xc3\xb3 tardana, cost O(n) en allotjament d\'operacions pendents d\'avaluarfoldl op estructInicial (x:xs) = foldl op (op estructInicial x) xs-- versi\xc3\xb3 estricta, avaluaci\xc3\xb3 primerencafoldl\' op estructInicial (x:xs) = let aplega_x = op estructInicial x_NEWLINE_                                  in aplega_x `seq` foldl\' op aplega_x xs-- (seq) aval\xc3\xbaa el primer operand i retorna el segon-- si el tipus de \'\'aplega_x\'\' \xc3\xa9s algebraic (cont\xc3\xa9 constructors (aturen l\'avaluaci\xc3\xb3)))_NEWLINE_L\'\xc3\xbas de tipus algebraics en l\'operaci\xc3\xb3, aturant l\'avaluaci\xc3\xb3 en els constructors, implica la generaci\xc3\xb3 d\'una pila de thunks (expressions pendents d\'avaluar) que poden comportar el sobreiximent de la pila.\n_START_SECTION_\nTipus primitius que es passen per valor (no encapsulats, ang:unboxed)\n_START_PARAGRAPH_\nVegeu-ho a GHC\n_START_SECTION_\nTuples no encapsulades per al retorn de m\xc3\xbaltiples valors\n_START_PARAGRAPH_\nVegeu-ho a GHC\n_START_SECTION_\nEspecialitzaci\xc3\xb3 d\'operacions sobrecarregades\n_START_PARAGRAPH_\nVegeu-ho a GHC\n_START_SECTION_\nRefer\xc3\xa8ncia r\xc3\xa0pida de la biblioteca\n_START_PARAGRAPH_\nA GHC.\n_START_SECTION_\nCol\xc2\xb7leccions amb components heterogenis - Emulaci\xc3\xb3 del despatx dels m\xc3\xa8todes virtuals de la O.O.\n_START_PARAGRAPH_\nVegeu ref. El #Tipus existencial d\xc3\xb3na soluci\xc3\xb3 al tractament de col\xc2\xb7leccions heterog\xc3\xa8nies incorporant els elements heterogenis com a components amb quantificaci\xc3\xb3 existencial (requerint que instanc\xc3\xafin les classes que aportin la operat\xc3\xb2ria requerida), sense trencar l\'homogene\xc3\xaftat de les col\xc2\xb7leccions._NEWLINE_{-# LANGUAGE ExistentialQuantification #-}module Forma (TForma(..), CForma(..)) whereimport Text.Printfimport Data.Function ((&))-- Farem una col\xc2\xb7lecci\xc3\xb3 de formes diverses que implementin CForma per obtenir-ne per\xc3\xadmetre i \xc3\xa0reaclass CForma t where_NEWLINE_  per\xc3\xadmetre :: t -> Double_NEWLINE_  \xc3\xa0rea :: t -> Double_NEWLINE_  nom :: t -> String-- tipus existencial (designa un cjt. de tipus amb caracter\xc3\xadstiques pr\xc3\xb2pies)--   caracter\xc3\xadstica: incorpora un component d\'aquells tipus \'\'t\'\' que implementin CForma_NEWLINE_ _NEWLINE_data TForma = forall t. CForma t => Forma t_NEWLINE_ _NEWLINE_-- implementaci\xc3\xb3 del tipus existencial amb--   despatx dels m\xc3\xa8todes propis als m\xc3\xa8todes del component_NEWLINE_ _NEWLINE_instance CForma TForma where_NEWLINE_  per\xc3\xadmetre (Forma forma) = per\xc3\xadmetre forma_NEWLINE_  \xc3\xa0rea (Forma forma) = \xc3\xa0rea forma_NEWLINE_  nom (Forma forma) = nom formainstance Show TForma where_NEWLINE_  show forma = printf format (forma & nom) (forma & per\xc3\xadmetre) (forma & \xc3\xa0rea)_NEWLINE_        where format = "(Forma %s: per\xc3\xadmetre %.2f, \xc3\xa0rea %.2f)\\n"_NEWLINE_module Cercle (TCercle, cercleNou) where_NEWLINE_ _NEWLINE_import Forma (CForma(..))_NEWLINE_ _NEWLINE_type TRadi = Double_NEWLINE_ _NEWLINE_data TCercle  = Cercle TRadi deriving (Eq, Show)_NEWLINE_ _NEWLINE_cercleNou :: TRadi -> Maybe TCerclecercleNou r_NEWLINE_  | r > 0 = Just (Cercle r)_NEWLINE_  | otherwise = Nothinginstance CForma TCercle where_NEWLINE_  per\xc3\xadmetre (Cercle r) = 2 * pi * r_NEWLINE_  \xc3\xa0rea (Cercle r) = pi * r ^ 2_NEWLINE_  nom _ = "Cercle"_NEWLINE_module Rectangle (TRectangle, rectangleNou) where_NEWLINE_ _NEWLINE_import Forma (CForma(..))_NEWLINE_ _NEWLINE_type TCostat = Double_NEWLINE_ _NEWLINE_data TRectangle = Rectangle TCostat TCostat deriving (Eq, Show)_NEWLINE_ _NEWLINE_rectangleNou :: TCostat -> TCostat -> Maybe TRectanglerectangleNou x y_NEWLINE_  | x > 0 && y > 0 = Just $ Rectangle x y_NEWLINE_  | otherwise = Nothing_NEWLINE_ _NEWLINE_instance CForma TRectangle where_NEWLINE_  per\xc3\xadmetre (Rectangle x y) = 2 * (x + y)_NEWLINE_  \xc3\xa0rea (Rectangle x y) = x * y_NEWLINE_  nom _ = "Rectangle"_NEWLINE_module Main whereimport Forma (TForma(..)) _NEWLINE_import Cercle (cercleNou)import Rectangle (rectangleNou)_NEWLINE_ _NEWLINE_formes :: [Maybe TForma]formes = [fmap Forma (cercleNou 2.4),_NEWLINE_          fmap Forma (rectangleNou 3.1 4.4),_NEWLINE_          fmap Forma (cercleNou (-2))]main = print formes_NEWLINE_runhaskell Main.hs_NEWLINE_d\xc3\xb3na la seg\xc3\xbcent sortida:_NEWLINE_[Just (Forma Cercle: per\xc3\xadmetre 15.08, \xc3\xa0rea 18.10)_NEWLINE__NEWLINE_,Just (Forma Rectangle: per\xc3\xadmetre 15.00, \xc3\xa0rea 13.64)_NEWLINE__NEWLINE_,Nothing]\n_START_SECTION_\nExpressions regulars\n_START_PARAGRAPH_\nVegeu-ho a Compilador Haskell de Glasgow#Expressions regulars\n_START_SECTION_\nLents de Van Laarhoven -- consulta i manipulaci\xc3\xb3 de parts d\'estructures complexes\n_START_PARAGRAPH_\nVegeu-ho a GHC\n_START_SECTION_\nEnt./Sort. amb fletxes de Kleisli (m\xc3\xb2nades elevades a fletxes)\n_START_PARAGRAPH_\nVegeu exemple a Fletxa (programaci\xc3\xb3 funcional)#Ent./Sort. amb fletxes de Kleisli (m\xc3\xb2nades elevades a fletxes)\n_START_SECTION_\nExtreure informaci\xc3\xb3 d\'un document XML\n_START_PARAGRAPH_\nVegeu exemple a Fletxa (programaci\xc3\xb3 funcional)\n_START_SECTION_\nPlantilles per a expressions, patrons, tipus i declaracions\n_START_PARAGRAPH_\nVegeu Compilador_Haskell_de_Glasgow#Quasi-Quotations (Plantilles)\n_START_SECTION_\nConcurr\xc3\xa8ncia simple amb MVars - Productor-consumidor\n_START_PARAGRAPH_\nVegeu-ho a Haskell concurrent\n_START_SECTION_\nCanals amb cues d\'entrada (Chan) - Client-servidor\n_START_PARAGRAPH_\nVegeu exemple a Haskell concurrent\n_START_SECTION_\nConcurr\xc3\xa8ncia condicionada amb variables transaccionals (TVar) - M\xc3\xb2nada STM (transaccions de mem\xc3\xb2ria per programari)\n_START_PARAGRAPH_\nVegeu exemple a Haskell concurrent\n_START_SECTION_\nParal\xc2\xb7lelisme\n_START_PARAGRAPH_\nVegeu Compilador_Haskell_de_Glasgow#Paral\xc2\xb7lelisme de tasques - Compilaci\xc3\xb3 per a processadors multicor\n_START_SECTION_\nParal\xc2\xb7lelisme de tasques - Compilaci\xc3\xb3 per a processadors multicor\n_START_PARAGRAPH_\nNom\xc3\xa9s a GHC. Vegeu Compilador Haskell de Glasgow#Paral\xc2\xb7lelisme de tasques - Compilaci\xc3\xb3 per a processadors multicor.\n_START_SECTION_\nAmb Estrat\xc3\xa8gies\n_START_PARAGRAPH_\nVegeu: Estrat\xc3\xa8gies i tamb\xc3\xa9 Reducci\xc3\xb3 en paral\xc2\xb7lel mitjan\xc3\xa7ant estrat\xc3\xa8gies\n_START_SECTION_\nAmb la m\xc3\xb2nada Par\n_START_PARAGRAPH_\nVegeu Haskell_concurrent#Futuribles -- Encadenament de c\xc3\xa0lculs as\xc3\xadncrons - la m\xc3\xb2nada Par\n_START_SECTION_\nParalel\xc2\xb7lisme d\'accions IO - El functor aplicatiu Concurrently\n_START_PARAGRAPH_\nVegeu Haskell_concurrent#Operacions d\'Entrada/Sortida as\xc3\xadncrones i simult\xc3\xa0nies\n_START_SECTION_\nAmb paral\xc2\xb7lelisme de dades DPH\n_START_PARAGRAPH_\nVegeu QuickSort amb Data Parallel Haskell\n_START_SECTION_\n\xc3\x9as de les instruccions SIMD sobre dades vectoritzades\n_START_PARAGRAPH_\nVegeu SIMD - Single Instruction, Multiple Data\n_START_SECTION_\nParal\xc2\xb7lelisme a GPUs (GPGPU) o equivalent (via OpenCL) sobre CPUs multicor\n_START_PARAGRAPH_\nVegeu Paral\xc2\xb7lelisme GPGPU\n_START_SECTION_\nConflictes de depend\xc3\xa8ncies\n_START_PARAGRAPH_\nTanmateix cal tenir en compte que l\'\xc3\xbas simultani de biblioteques que facin servir diferents versions d\'un mateix paquet \xc3\xa9s molt problem\xc3\xa0tic. Cal evitar absolutament la comanda cabal upgrade que ens abocaria al problema esmentat.\n_START_SECTION_\nEl rebost Stackage - rebost alternatiu amb depend\xc3\xa8ncies verificades\n_START_PARAGRAPH_\nStackage proporciona imatges de conjunts de biblioteques amb compatibilitat verificada de versions, entre elles i una versi\xc3\xb3 espec\xc3\xadfica de GHC, amb noves imatges dels rebostos a mesura que sorgeixen noves versions de depend\xc3\xa8ncies o del compilador._NEWLINE_Vegeu Compilador Haskell de Glasgow#Stackage - rebost alternatiu amb depend\xc3\xa8ncies verificades\n_START_SECTION_\nGesti\xc3\xb3 dels paquets instal\xc2\xb7lats\n_START_PARAGRAPH_\nAmb ghc-pkg comprova paquets instal\xc2\xb7lats a les BDD de paquets de l\'usuari i del sistema._NEWLINE_$ ghc-pkg list _NEWLINE__NEWLINE_$ ghc-pkg check            # comprova depend\xc3\xa8ncies trencades per la reinstal\xc2\xb7laci\xc3\xb3 d\'aquestes_NEWLINE_En un entorn de desenvolupament a\xc3\xafllat en capsa-de-proves (sandbox):_NEWLINE_cabal sandbox hc-pkg ...\n_START_SECTION_\nInstal\xc2\xb7laci\xc3\xb3 des del GitHub\n_START_PARAGRAPH_\nL\'aplicaci\xc3\xb3 cabalg descarrega (amb git-clone a subcarpeta) i instal\xc2\xb7la (amb cabal)._NEWLINE_cabalg https://github.com/usuari/projecte-github  # descarrega a subcarpeta de nom "projecte-github"\n_START_SECTION_\nThe Haskell Platform\n_START_PARAGRAPH_\nThe Haskell Platform vol ser un instal\xc2\xb7lador empaquetant el compilador GHC (nom\xc3\xa9s a Windows, a Unix i derivats cal descarregar-lo pr\xc3\xa8viament), una biblioteca i un paquet d\'eines incorporant paquets de rutines del rebost Hackage. amb encaix verificat respecte a la versi\xc3\xb3 de la biblioteca Base inclosa. (Preguntes freq\xc3\xbcents)'