































Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Este documento aborda a construção de módulos em haskell, com foco na importação de outros módulos e na aplicação de regras para a construção de funções. Além disso, são apresentadas funções básicas, como dobro e triplo, e a noção de linguagens com e sem tipos, destacando as vantagens das linguagens com disciplina de tipos rigorosa. Também é introduzido o conceito de tipos enumeráveis em haskell, como o tipo char, e funções para conversão entre inteiros e caracteres. Por fim, é apresentada a sintaxe para definição de funções em haskell.
Tipologia: Resumos
1 / 39
Esta página não é visível na pré-visualização
Não perca as partes importantes!
































(^1) Departamento de Matem´atica da Universidade de Coimbra.
A linguagem Haskell 1 (Bird, 1998; Hammond et al., 1997; Hudak, 2000; Hudak et al., 1997; Hutton, 2007; Peterson et al., 1997; Thompson, 1996) ´e uma linguagem funcional^2 (pura) com tipos de dados bem definidos (Bird, 1998), ou seja, os modelos para as estruturas de informa¸c˜ao s˜ao baseados na Teoria dos Conjuntos, e as opera¸c˜oes s˜ao descritas atrav´es de fun¸c˜oes entre conjuntos. Os programas mais divulgados para se trabalhar com a linguagem Haskell s˜ao o interpretador Hugs^3 (Jones & Peterson, 1997) e o compilador e interpretador GHC – the Glasgow Haskell Compiler 4 sendo que este ´ultimo providencia tamb´em um interpretador, o GHCI, com um modo de utiliza¸c˜ao idˆentica ao Hugs. A diferen¸ca mais vis´ıvel entre um compilador e um interpretador ´e dada pela inte- rac¸c˜ao com o utilizador. No caso de um compilador ´e necess´ario utilizar um editor de texto para escrever um programa que ´e depois transformado pelo compilador de uma forma autom´atica num execut´avel. No caso do interpretador n˜ao s´o ´e poss´ıvel escrever programas e avali´a-los atrav´es do pr´oprio interpretador (no caso do Hugs e do GHCI s´o ´e poss´ıvel calcular o valor de express˜oes), como no caso de se utilizar um editor externo para a escrita do programa ´e depois necess´ario ter o interpretador em mem´oria de forma a executar o programa. Os interpretadores permitem uma testagem dos programas de uma forma interactiva o que no caso de uma linguagem funcional (fun¸c˜oes independentes umas das outras) ´e bastante interessante. De seguida vai-se centrar a aten¸c˜ao na utiliza¸c˜ao dos interpretadores pois ser´a esta a forma mais usual de desenvolver programas em Haskell.
1.1 Utiliza¸c˜ao dos Interpretadores
Ao invocar-se o interpretador este carrega de imediato o m´odulo Prelude.hs, que constitui o m´odulo b´asico da linguagem Haskell. Toda a interac¸c˜ao com o programa Hugs, ou GHCi (The GHC Team, n.d.) desenvolve- se no ˆambito de um dado m´odulo, tal facto ´e posto em evidˆencia na linha de comando do programa:
Prelude>
(^1) http://www.haskell.org/ (^2) http://www.mat.uc.pt/~pedro/cientificos/Funcional.html (^3) http://www.haskell.org/hugs/ (^4) http://www.haskell.org/ghc/
1.2. UTILIZAC¸ AO DO COMPILADOR˜ GHC Vers˜ao 1.4 4
Se se invocar o interpretador conjuntamente com o nome de um ficheiro, j´a previa- mente constru´ıdo, e que contenha um m´odulo, por exemplo Fact.hs, contendo o m´odulo Fact, a linha de comando do interpretador passar´a a ser:
Fact>
A interac¸c˜ao com o interpretador limitar-se-´a a:
1.2 Utiliza¸c˜ao do Compilador ghc
A utiliza¸c˜ao do compilado ghc (The GHC Team, n.d.) requer que se defina o m´odulo Main e, dentro deste, a fun¸c˜ao zero-´aria main. Na constru¸c˜ao deste modo aplicam- se todas as regras que veremos a frente para a constru¸c˜ao de m´odulos em Haskell, nomeadamente a importa¸c˜ao de outros m´odulos. Vejamos como ´e que poderiamos construir ent˜ao um execut´avel que nos desse o valor da fun¸c˜ao de Ackermann para os valores de entrada 3 e 9. Primeiro definia-se um m´odulo (ficheiro) para a fun¸c˜ao de Ackermann (veremos os pormenores de uma tal defini¸c˜ao maisa frente.
module Ackermann(ackermann) where ackermann :: (Integer,Integer) → Integer ackermann (0,y) = y+ 1 ackermann (x,0) = ackermann(x-1,1) ackermann (x,y) = ackermann(x-1,ackermann(x,y-1)) De seguida constro´ı-se o m´odulo Main que mais n˜ao faz do que importar o m´odulo definido acima, definir um ponto de entrada o qual deve ter como resultado a escrita do valor que se pretende mostrar.
module Main where import Ackermann
main=print (ackermann (3,7)) Finalmente ´e s´o uma quest˜ao de usar o compilador ghc para produzir o execut´avel.
1.3. ESCRITA DE PROGRAMAS EM HASKELL Vers˜ao 1.4 6
dobro x = 2 ∗x ; triplo x = 3 ∗x
O desenvolvimento de programas em Haskell ´e muito facilitado caso se use o editor (X)emacs, caso em que se pode usar o haskell-mode^5 , um modo de edi¸c˜ao do (X)emacs especializado para o desenvolvimento de programas em Haskell. De seguida transcreve-se a informa¸c˜ao (C-h m) existente para este modo.
Haskell mode: Major mode for editing Haskell programs. Last adapted for Haskell 1.4. Blank lines separate paragraphs, comments start with ‘-- ’.
M-; will place a comment at an appropriate place on the current line. C-c C-c comments (or with prefix arg, uncomments) each line in the region.
Literate scripts are supported via ‘literate-haskell-mode’. The variable ‘haskell-literate’ indicates the style of the script in the current buffer. See the documentation on this variable for more details.
Modules can hook in via ‘haskell-mode-hook’. The following modules are supported with an ‘autoload’ command:
‘haskell-font-lock’, Graeme E Moss and Tommy Thorn Fontifies standard Haskell keywords, symbols, functions, etc.
‘haskell-decl-scan’, Graeme E Moss Scans top-level declarations, and places them in a menu.
‘haskell-doc’, Hans-Wolfgang Loidl Echoes types of functions or syntax of keywords when the cursor is idle.
‘haskell-indent’, Guy Lapalme Intelligent semi-automatic indentation.
‘haskell-simple-indent’, Graeme E Moss and Heribert Schuetz Simple indentation.
‘haskell-hugs’, Guy Lapalme Interaction with Hugs interpreter.
Module X is activated using the command ‘turn-on-X’. For example, ‘haskell-font-lock’ is activated using ‘turn-on-haskell-font-lock’. For more information on a module, see the help for its ‘turn-on-X’ function. Some modules can be deactivated using ‘turn-off-X’. (Note that ‘haskell-doc’ is irregular in using ‘turn-(on/off)-haskell-doc-mode’.) (^5) http://www.haskell.org/haskell-mode/
1.3. ESCRITA DE PROGRAMAS EM HASKELL Vers˜ao 1.4 7
Use ‘haskell-version’ to find out what version this is.
Invokes ‘haskell-mode-hook’ if not nil.
Font-Lock minor mode (indicator Font): Toggle Font Lock Mode. With arg, turn font-lock mode on if and only if arg is positive.
When Font Lock mode is enabled, text is fontified as you type it:
and
Where modes support different levels of fontification, you can use the variable ‘font-lock-maximum-decoration’ to specify which level you generally prefer. When you turn Font Lock mode on/off the buffer is fontified/defontified, though fontification occurs only if the buffer is less than ‘font-lock-maximum-size’. To fontify a buffer without turning on Font Lock mode, and regardless of buffer size, you can use M-x font-lock-fontify-buffer.
See the variable ‘font-lock-keywords’ for customization.
Column-Number minor mode (indicator): Toggle Column Number mode. With arg, turn Column Number mode on iff arg is positive.
O Haskell ´e uma linguagem de programa¸c˜ao com uma disciplina de tipos rigorosa (“stron- gly typed”), quer isto dizer que toda a entidade num programa em Haskell tem um, e um s´o, tipo, sendo sempre poss´ıvel determinar o tipo de uma determinada entidade. O contra-ponto deste tipo de linguagem s˜ao as linguagens sem tipos, ou melhor lingua- gens em que todas as entidades partilham um mesmo tipo, um exemplo deste tipo de linguagens ´e a linguagem Lisp. Existem argumentos a favor e contra cada uma destas duas aproxima¸c˜oes, uma das grandes vantagens das linguagens com uma disciplina de tipos rigorosa reside na possibilidade de constatar a correc¸c˜ao dos programas atrav´es da verifica¸c˜ao dos tipos, as linguagens deste tipo s˜ao tamb´em as que melhor suportam a modularidade e a abstrac¸c˜ao. Em termos pr´aticos temos que um dado elemento tem sempre um tipo bem definido, de igual modo toda e qualquer fun¸c˜ao tem um dom´ınio e um co-dom´ınio bem definidos. Em Haskell temos ent˜ao um conjunto de tipos de base, pr´e-definidos, e um conjunto de construtores que permitem ao programador criar novos tipos a partir dos tipos de base.
2.1 Tipos de Base
O Haskell possui os seguintes tipos de base:
Existe ainda o tipo Vazio, Void, que vai ser importante aquando da defini¸c˜ao de fun¸c˜oes parciais. O ´unico elemento deste tipo, ⊥, ´e interpretado como o valor indefinido,
2.1. TIPOS DE BASE Vers˜ao 1.7 10
permitindo deste modo a defini¸c˜ao de fun¸c˜oes que s˜ao indefinidas para certa classe de argumentos. E de notar que, em consequˆ´ encia do que se acabou de dizer, o elemento ⊥ vai pertencer a todos os tipos. Conven¸c˜ao Sint´actica: Os identifi- cadores dos elementos come¸cam por uma letra min´uscula, os identificado- res de tipos, e os identifi- cadores dos construtores come¸cam por uma letra mai´uscula.
Vejamos cada um destes tipos mais em pormenor:
O tipo unit´ario, Unit, ´e uma implementa¸c˜ao do conjunto 1.
Tipo () Valores ()
Valores L´ogicos e s´ımbolos proposicionais para uma l´ogica proposicional bivalente.
Tipo Bool Valores True; False; otherwise ( = True). Operadores && (conjun¸c˜ao); ‖ (disjun¸c˜ao); not (nega¸c˜ao) Predicados ==, / =, <, <=, >=, >
Os identificadores True, e False correspondem aos dois construtores 0-´arios do con- junto Bool. O identificador otherwise, cujo valor ´e igual a True vai ser ´util aquando da defini¸c˜ao de fun¸c˜oes com ramos.
Caracteres, s´ımbolos do alfabeto “Unicode”.
Tipo Char Valores s´ımbolos da Tabela Unicode entre plicas, por exemplo ’a’ Operadores
A exemplo de outras linguagens o Haskell possui um conjunto de caracteres especiais: ’\t’, espa¸co tabular (tab); ’\n’, mudan¸ca de linha (newline); ’\’ barra inclinada para tr´as, (backslash); ’\’’, plica; ’" ’, aspas.
Tem-se acesso as duas fun¸c˜oes de transferˆencia usuais entre valores do tipo Char e valores do tipo Int, estas fun¸c˜oes designam-se por: ord :: Char -> Int e chr :: Int -> Char. Al´em destas fun¸c˜oes temos tamb´em acessoas fun¸c˜oes de transferˆencia definidas para todo e qualquer tipo enumerado. No caso do tipo Char estas fun¸c˜oes tˆem valores inteiros entre 0 e 2^16 − 1 inclusiv´e:
toEnum (Int → Char), por exemplo (toEnum 97)::Char = ’a’;
fromEnum (Char → Int), por exemplo fromEnum ’a’ = 97.
2.2. TIPOS ESTRUTURADOS Vers˜ao 1.7 12
Tipo Void Valores ⊥
Dado que o Haskell ´e uma linguagem n˜ao-estrita (veremos mais `a frente o significado preciso desta afirma¸c˜ao) o valor ⊥ (indefinido) est´a presente em todos os tipos.
2.2 Tipos Estruturados
O Haskell possui um conjunto de construtores de tipos que possibilitam a constru¸c˜ao de novos tipos a partir dos tipos de base. Temos assim a possibilidade de construir novos tipos a partir do co-produto, do produto, e da exponencia¸c˜ao de conjuntos.
O tipo correspondente a um dado n-uplo implementa o produto cartesiano dos tipos que comp˜oem o n-uplo.
T = T 1 × T 2 × · · · × Tm
Tipo (T 1 ,...,Tn) Valores (e 1 ,...,ek), com k ≥ 2 Construtores (,...,) Operadores fst, snd, s´o aplic´aveis a pares.
Os operadores fst(x,y) = x, e snd(x,y)=y d˜ao-nos as duas projec¸c˜oes pr´oprias do produto cartesiano.
O Haskell possu´ı tamb´em tipos definidos por enumera¸c˜ao, podemos por exemplo consi- derar que os tipos simples podem ser definidos desse modo. O tipo co-produto implementa o co-produto de conjuntos, ou dito de outra forma, a uni˜ao disjunta de conjuntos.
T = T 1 + T 2 + · · · + Tm
Tipo T 1 |... |Tn. Com Ti um tipo, ou um construtor un´ario. Valores e, com e um elemento de um dos tipos que definem o co-produto. Construtores os construtores dos diferentes tipos, assim como cons- trutores un´arios definidos caso a caso.
A defini¸c˜ao de tipos por enumera¸c˜ao, e a utiliza¸c˜ao dos contructores pr´oprios dos co-produtos ir´a ser explorada mais `a frente aquando do estudo da defini¸c˜ao de novos tipos em Haskell.
2.2. TIPOS ESTRUTURADOS Vers˜ao 1.7 13
O conjunto das sequˆencias finitas, eventualmente vazias, de elementos de um dado tipo A, isto ´e, A∗^ = A^0 +A^1 +A^2 +· · ·+An, ´e implementado atrav´es do tipo listas homog´eneas. Para um dado tipo de base A temos:
Lista A = Vazia+A×Lista A
Tipo [A], listas de elementos de um tipo A Valores [] (lista vazia); [e 0 ,...,em] (lista n˜ao vazia) Construtores [] : 1 −→ Lista ∗ 7 −→ [] : : A × Lista A −→ Lista A (a,l) 7 −→ l′^ = a:l [e 0 ,e 1 ,...,em] =. e 0 :(e 1 :(...:(em : [])...)) Operadores ++, head, last, tail, init, nul, length, !!, foldl, foldl1, scanl, scanl1, foldr, foldr1, scanr, scanr1, iterate, repeat, replicate, cycle, take, drop, splitAt, takeWhile, dropWhile, span, break, lines, words, mlines, mwords, reverse, and, or, any, all, elem, notElem, lookup, sum, product, maximun, minimun, concatMap, zip, zip3, zipWith, zipWith3, unzip, unzip
De entre de todos estes operadores vejamos a defini¸c˜ao de last e de init: last([e 0 ,e 1 ,...,em]) = em init([e 0 ,e 1 ,...,em]) = [e 0 ,e 1 ,...,em− 1 ] O operador !! permite usar uma lista como uma tabela uni-dimensional com ´ındices a come¸car no zero. Por exemplo: [e 0 ,e 1 ,...,em] !! k = ek, 0 ≤ k ≤ m O operador ++ d´a-nos a concatena¸c˜ao de duas listas. Por exemplo: [1,2,3]++[4,5,6] = [1,2,3,4,5,6] O Haskell possu´ı duas formas de constru¸c˜ao de listas sem que para tal seja necess´ario escrever a lista com todos os seus elementos. Vejamos de seguida esses dois mecanismos.
Defini¸c˜ao de uma lista atrav´es de uma gama de varia¸c˜ao. Podemos definir uma lista de elemento num´ericos atrav´es dos seus limites, ou ainda atrav´es dos seus limites e do incremento entre valores. Vejamos esses dois casos:
2.3. EXPRESS OES˜ Vers˜ao 1.7 15
As fun¸c˜oes v˜ao estar subjacentes a todas as manipula¸c˜oes da linguagem e implementam a exponencia¸c˜ao de conjuntos. Ou seja o conjunto de todas as fun¸c˜oes de A para B ´e dado por BA.
Tipo T 1 -> T 2 Valores id, const,... Construtores \ x -> exp(x) Operadores ·, curry, uncurry,...
O operador “·” d´a-nos a composi¸c˜ao de fun¸c˜oes. Os operadores curry e uncurry verificam, curry f x y = f (x,y) e uncurry f p = f (fst p) (snd p). A abstrac¸c˜ao lambda permite-nos definir uma fun¸c˜ao sem lhe dar um nome, o que n˜ao nos impede a sua aplica¸c˜ao a um dado argumento. Por exemplo (\x -> x^2) 4 daria o resultado 16. Embora a defini¸c˜ao de fun¸c˜oes seja habitualmente feita de forma diferente (mais `a frente veremos como), pode-se atribuir um nome a uma fun¸c˜ao definida atrav´es da abstrac¸c˜ao lambda, por exemplo quadrado = (\x -> x^2)
2.3 Express˜oes
A linguagem Haskell ´e uma linguagem com uma disciplina de tipos rigorosa, quer isto dizer que qualquer express˜ao em Haskell tem um e um s´o tipo bem definido. A este prop´osito ´e de referir uma s´erie de comandos que se revelam interessantes; um deles ´e o comando :type (ou :t). Este comando d´a-nos, para uma determinada express˜ao, a informa¸c˜ao acerca do tipo da express˜ao. Por exemplo:
Prelude> :t ’a’ ’a’ :: Char
A sintaxe
Prelude> 7+ 10 Prelude> :set +t Prelude> 7+ 10 :: Int
A avalia¸c˜ao de uma express˜ao ´e feita por redu¸c˜ao da express˜ao `a sua forma normal. Podemos modificar o comportamento do interpretador de forma a que este explicite da- dos estat´ısticos (:set +s) acerca das redu¸c˜oes necess´arias para a avalia¸c˜ao da express˜ao. Por exemplo
2.3. EXPRESS OES˜ Vers˜ao 1.7 16
Prelude> :set +s Prelude> 7+ 10 :: Int (10 reductions, 10 cells)
Posto isto a escrita de express˜oes e a sua avalia¸c˜ao segue as regras usuais. Por exemplo:
Prelude> "Haskell" "Haskell" :: String Prelude> 5+3* 35 :: Int Prelude> head [3,56,79] 3 :: Int Prelude> fst (’a’,1) ’a’ :: Char Prelude> 4*1. 4.0 :: Double
A precedˆencia dos v´arios operadores assim como o modo como se procede a sua asso- cia¸c˜ao ´e dada na seguinte tabela.
Precedˆencia associa a esquerda associaa direita n˜ao associativo 9 !!. — 8 — ^,^^,** — 7 *,/,‘div‘,‘mod‘, ‘rem‘,‘quot‘
‘elem‘,‘notElem‘ 3 — && — 2 — || — 1 >>,>>= — — 0 — $,‘seq‘ —
3.1. DEFINIC¸ OES SIMPLES˜ Vers˜ao 1.8 18
3.1 Defini¸c˜oes Simples
A defini¸c˜ao de uma fun¸c˜ao passa pela escrita de uma “equa¸c˜ao” que determine o seu comportamento. A sintaxe ´e a seguinte:
< nome da fun¸c˜ao > < argumento > = < express˜ao >
por exemplo
cubo x = x∗x∗x
A defini¸c˜ao de fun¸c˜oes deve ser entendida como uma regra de re-escrita da esquerda para a direita, a qual est´a implicitamente quantificada universalmente nas suas vari´aveis. Ou seja a leitura da defini¸c˜ao de cubo ´e a seguinte:
∀x∈T cubo x → x × x × x
com T um dos tipos da linguagem Haskell, e → o operador de redu¸c˜ao. A avalia¸c˜ao de uma express˜ao que envolva a fun¸c˜ao cubo passa pela redu¸c˜ao da express˜ao `a sua forma normal, utilizando, entre outras, a regra de redu¸c˜ao escrita acima. Por exemplo:
Main> cubo 3 27
teve como passos da redu¸c˜ao cubo 3 → (3 × 3) × 3 → 9 × 3 → 27. Qual ´e o tipo da fun¸c˜ao cubo
Main> :t cubo cubo :: Num a ⇒ a → a
A resposta aparentemente confusa tem a seguinte leitura, cubo ´e uma fun¸c˜ao de dom´ınio A e co-dom´ınio A (a -> a) em que A ´e um qualquer tipo num´erico (Num a =>). Ou seja cubo ´e uma fun¸c˜ao polim´orfica cujo tipo (a->a) pertence `a classe dos tipos num´ericos (Num a). A defini¸c˜ao de uma instˆancia concreta para a fun¸c˜ao cubo s´o acontece no momento da avalia¸c˜ao. Um outro ponto que importa salientar ´e que as fun¸c˜oes em Haskell tˆem um, e um s´o, argumento. Como proceder ent˜ao para definir uma fun¸c˜ao a aplicar a dois argumentos? Existem duas solu¸c˜oes poss´ıveis: Em primeiro podemos agrupar os argumentos num n-uplo. Por exemplo:
soma1 :: (Int,Int) → Int soma1 (x,y) = x + y
A outra solu¸c˜ao ´e dada pela defini¸c˜ao de uma fun¸c˜ao curry.
soma2 :: Int → (Int → Int) soma2 x y = x + y
Estas duas defini¸c˜oes s˜ao equivalentes dado serem a express˜ao da propriedade uni- versal das fun¸c˜oes. E de relembrar que a aplica¸´ c˜ao de fun¸c˜oes associa `a esquerda, ou seja soma x y deve ler-se como (soma x) y. A vantagem da utiliza¸c˜ao de fun¸c˜oes curry em detrimento das fun¸c˜oes n˜ao-curry ´e dupla: por um lado utilizam-se argumentos n˜ao estruturados tornando deste modo a escrita mais simples; por outro lado ao aplicar-se uma fun¸c˜ao curry a um dos seus argu- mentos obtˆem-se uma outra fun¸c˜ao que pode por sua vez ser um objecto interessante.
3.2. DEFINIC¸ OES CONDICIONAIS˜ Vers˜ao 1.8 19
3.2 Defini¸c˜oes Condicionais
A defini¸c˜ao de uma fun¸c˜ao atrav´es de uma ´unica equa¸c˜ao n˜ao nos permite definir fun¸c˜oes por ramos. Temos duas possibilidades para o fazer: atrav´es de express˜oes condicionais.
menor1 :: (Int,Int) → Int menor1 (x,y) = if x ≤ y then x else y
ou ent˜ao atrav´es de equa¸c˜oes com “guardas”.
menor2 :: (Int,Int) → Int menor2 (x,y) | x ≤ y = x | x > y = y As duas defini¸c˜oes s˜ao equivalentes, no segundo caso as “guardas” s˜ao avaliados e a primeira a tomar o valor l´ogico de verdade determina o valor da fun¸c˜ao. A segundo defini¸c˜ao podia ser re-escrita do seguinte modo:
menor3 :: (Int,Int) → Int menor3 (x,y) | x > y = y | otherwise = x
dado que o valor l´ogico de otherwise ´e Verdade, ent˜ao este padr˜ao determina o valor da fun¸c˜ao para todos os casos em que os outros ramos que o precedem n˜ao tenham o valor l´ogico de Verdade.
3.3 Defini¸c˜oes Recursivas
A defini¸c˜ao de fun¸c˜oes recursivas em Haskell n˜ao s´o ´e poss´ıvel, como a sua sintaxe ´e muito simples, e segue de perto a sintaxe matem´atica. Por exemplo a defini¸c˜ao da fun¸c˜ao factorial ´e dada por:
fact :: Integer → Integer fact n | n == 0 = 1 | n > 0 = n∗fact(n-1) Na defini¸c˜ao desta fun¸c˜ao levanta-se uma quest˜ao: e no caso em n < 0? Para os valores de n < 0 a fun¸c˜ao factorial n˜ao est´a definida, ela ´e uma fun¸c˜ao parcial no conjunto dos inteiros, torna-se ent˜ao necess´ario saber lidar com fun¸c˜oes parciais. Em Haskell a forma de lidar com fun¸c˜oes parciais passa por especificar situa¸c˜oes de erro.
fact1 :: Integer → Integer fact1 n | n < 0 = error "A fun¸c~ao fact n~ao est´a definida para n<0" | n == 0 = 1 | n > 0 = fact1(n-1)∗n No entanto, e dado o tipo da fun¸c˜ao fact1, a fun¸c˜ao error tem de ser String -> Integer. O tipo da fun¸c˜ao error ´e na verdade String -> A, com A um tipo Haskell, ou seja error ´e uma fun¸c˜ao polim´orfica cujo tipo do co-dom´ınio depende da situa¸c˜ao em que ´e aplicada. O mesmo se passa com a fun¸c˜ao ‘*’, o seu tipo ´e A -> A -> A, sendo depois ins- tanciada para uma dada fun¸c˜ao concreta no momento da aplica¸c˜ao.