Você está na página 1de 170

Introduo Programao

uma Abordagem FuncionaI


Credin SiIva de Menezes,
Maria CIaudia SiIva Boeres,
Maria Christina VaIIe Rauber,
Thais HeIena Castro,
AIberto Nogueira de Castro Jnior,
CIudia GaIarda Varassin
Departamento de Informtica - UFES
Departamento de Cincia da Computao - UFAM
2008
1
ndice
1. CONCETOS BSCOS ................................................................................ 4
2. A LNGUAGEM DE PROGRAMAO HASKELL E O AMBENTE HUGS 12
3. A ARTE DE RESOLVER PROBLEMAS ..................................................... 21
4. ABSTRAO, GENERALZAO, NSTANCAO E MODULARZAO
................................................................................................................................. 28
5. TPOS DE DADOS NUMRCOS ............................................................... 36
6. EXPRESSES LGCAS E O TPO BOOLEAN ....................................... 51
7. DEFNES CONDCONAS ................................................................... 59
8. O TESTE DE PROGRAMAS ...................................................................... 66
9. RESOLVENDO PROBLEMAS - OS MOVMENTOS DO CAVALO ........... 72
10. TUPLAS ..................................................................................................... 81
11. VALDAO DE DADOS .......................................................................... 86
12. LSTAS ...................................................................................................... 91
13. RESOLVENDO PROBLEMAS COM LSTAS ......................................... 105
14. PARADGMA APLCATVO .................................................................... 109
15. Processamento de Cadeias de Caracteres primeiros passos ............. 120
16. O PARADGMA RECURSVO ................................................................ 127
17. ORDENAO RECURSVA DE DADOS...............................................142
18. APLCAES ......................................................................................... 152
19. ENTRADA E SADA DE DADOS ............................................................ 168
2
1. CONCEITOS BSICOS
1.1 INTRODUO
Neste curso o leitor estar se envolvendo com a aprendizagem de conceitos e
mtodos bsicos para a construo de programas de computador. A
abordagem que daremos est voltada para o envolvimento do aprendiz com a
soluo de problemas ao invs da atitude passiva de ver o que os outros
fizeram. Uma questo central que permeia o curso a de que construir
programas uma tarefa de engenharia, e que, portanto produzir artefatos com
os quais o ser humano ter de conviver. Artefatos estes que devem satisfazer
requisitos de qualidade e serem, portanto, passveis de constatao.
Optamos desenvolver a disciplina orientada descrio de funes, um
formalismo bastante conhecido por todos os que chegam a este curso.
Esperamos, com isso, atenuar algumas dificuldades tpicas do ensino
introdutrio de programao. Nas sees seguintes apresentamos alguns
conceitos bsicos que nos parecem importantes ter em mente antes de
iniciarmos um curso de programao.
1.2. COMPUTADORES
Denominamos computador uma mquina de processar dados, numricos ou
simblicos, que funciona atravs da execuo de programas. Ao contrrio das
inmeras mquinas que conhecemos, tais como mquina de lavar roupa,
liquidificador, aspirador de p, e tantas outras, que realizam uma nica funo,
o computador uma mquina multi-uso. Podemos us-lo como uma mquina
de escrever sofisticada, como uma mquina de fax, como uma prancheta de
desenho sofisticada, como um fichrio eletrnico, como uma planilha de
clculos e de tantas outras formas. exatamente como o nosso conhecido
videogame: para mudar de jogo basta trocar o cartucho. No videogame, cada
novo jogo determinado por um novo programa.
Em linhas gerais podemos entender um computador como uma mquina
capaz de:
a) interpretar dados que lhe so fornecidos, produzindo
resultados em forma de novos dados, usando para isso
conceitos que lhe foram antecipadamente informados e,
b) aceitar a descrio de novos conceitos e consider-los na
interpretao de novas situaes.
Alguns exemplos de uso de um computador:
1) Descrever para uma mquina a relao mtrica que existe entre os
lados de um tringulo retngulo. De posse desse conhecimento, a mquina
poderia, por exemplo, determinar o valor de um dos lados quando conhecido o
valor dos outros dois.
3
2) nformar a uma mquina as regras de conjugao de verbos. Com este
conhecimento a mquina pode determinar a forma correta para um
determinado tempo e pessoa de um verbo especfico.
3) Traduo de textos;
4) Classificao de textos quanto sua natureza: romance, poesia,
documentrio, entrevista, artigo cientfico;
5) Manipulao de expresses algbricas, resoluo de integral
indefinida, etc;
6) Programao automtica: dada uma certa especificao, gerar um
programa eficiente;
7) Monitoramento de pacientes em um Centro de Tratamento ntensivo;
8) dentificao de tumores no crebro a partir da comparao de
imagens com padres conhecidos de anormalidade;
9) Roteamento inteligente de mensagens;
10) Monitoramento de regies por satlite.
1.3. PROGRAMAO
tarefa de identificar o conhecimento necessrio para a descrio de um
conceito, organiz-lo e codific-lo de modo a ser entendido pela mquina
damos o nome de programao de computadores. Ao conhecimento
codificado, produto final da tarefa de programao d-se o nome de programa.
A programao de computadores uma atividade que compreende vrias
outras atividades, tais como: entendimento do problema a ser resolvido,
planejamento de uma soluo, formalizao da soluo usando uma linguagem
de programao, verificao da conformidade da soluo obtida com o
problema proposto.
1.4. LINGUAGEM DE PROGRAMAO
A descrio de conhecimento para um agente racional qualquer (seja uma
mquina ou um humano) subentende a existncia de padres segundo os
quais o agente possa interpretar o conhecimento informado. A esses padres,
quando rigorosamente elaborados, damos o nome de formalismo. Um
formalismo composto de dois aspectos: a sintaxe e a semntica. A sintaxe
permite ao agente reconhecer quando uma "seqncia de smbolos" que lhe
fornecida est de acordo com as regras de escrita e, portanto representa um
programa. A semntica permite que o agente atribua um significado ao
conhecimento descrito pela "seqncia de smbolos". Por exemplo, quando um
agente humano (com determinado grau de escolaridade) encontra a seguinte
seqncia de smbolos {3, 4} U {5, 9, 15}, ele por certo reconhecer como uma
expresso algbrica escrita corretamente e, se lembrar dos fundamentos da
4
teoria dos conjuntos, associar esta cadeia como a descrio de um conjunto
composto pela unio dos elementos de dois conjuntos menores.
Eis aqui algumas observaes importantes sobre a necessidade de
linguagens de programao:
Ainda no possvel usar linguagem natural para ensinar o
computador a realizar uma determinada tarefa. A linguagem
natural, to simples para os humanos, possui ambigidades e
redundncias que a inviabilizam como veculo de comunicao
com os computadores.
A linguagem nativa dos computadores muito difcil de ser usada,
pois requer do programador a preocupao com muitos detalhes
especficos da mquina, tirando pois ateno do problema.
Para facilitar a tarefa de programao foram inventadas as
linguagens de programao. Estas linguagens tm por objetivo se
colocarem mais prximas do linguajar dos problemas do que do
computador em si. Para que o programa que escrevemos possa
ser "entendido pelo computador, existem programas especiais que
os traduzem (compiladores) ou os que interpretam
(interpretadores) para a linguagem do computador.
Podemos fazer um paralelo com o que ocorre quando queremos
nos comunicar com uma pessoa de lngua estrangeira. Podemos
escrever uma carta em nossa lngua e pedir a algum que a
traduza para a lngua de nosso destinatrio ou se quisermos
conversar pessoalmente, podemos usar um intrprete.
1.5. PROPRIEDADES DE UM PROGRAMA
Fazemos programas com a inteno de dotar uma mquina da capacidade de
resolver problemas. Neste sentido, um programa um produto bem definido,
que para ser usado precisa que sejam garantidas algumas propriedades. Aqui
fazemos referncias a duas delas: a correo e o desempenho. A correo
pode ser entendida como a propriedade que assegura que o programa
descreve corretamente o conhecimento que tnhamos inteno de descrever. O
desempenho trata da propriedade que assegura que o programa usar de
forma apropriada o tempo e os recursos da mquina considerada. Cabe aqui
alertar aos principiantes que a tarefa de garantir que um programa foi
desenvolvido corretamente to complexa quanto prpria construo do
programa em si. Garantir que um programa funciona corretamente condio
imprescindvel para o seu uso e, portanto estaremos dando maior nfase a esta
propriedade.
1.6. PARADIGMAS DE LINGUAGENS DE PROGRAMAO
As regras que permitem a associao de significados s "seqncias de
smbolos" obedecem a certos princpios. Existem vrias manifestaes destes
princpios e a cada uma delas denominamos de paradigma.
Um paradigma pode ser entendido informalmente como uma forma
especfica de se "pensar" sobre programao. Existem trs grandes grupos de
5
paradigmas para programao: o procedimental (ou procedural), o funcional e
o lgico. Os dois ltimos so freqentemente referidos como sendo
subparadigmas de um outro mais geral, o paradigma declarativo. O paradigma
procedimental subentende a organizao do conhecimento como uma
seqncia de tarefas para uma mquina especfica. O paradigma lgico requer
o conhecimento de um formalismo matemtico denominado lgica matemtica.
O paradigma funcional baseia-se no uso dos princpios das funes
matemticas. De uma forma geral, os paradigmas declarativos enfatizam o
aspecto correo e o procedimental os aspectos de desempenho. Vejam que
falamos em "enfatizam", o que quer dizer que apresentam facilidades para
descrio e verificao da propriedade considerada. Entretanto, em qualquer
caso, o programador dever sempre garantir que os dois aspectos (correo e
desempenho) sejam atendidos.
1.7. PROGRAMAO FUNCIONAL
Para os fins que aqui nos interessam neste primeiro momento, podemos
entender o computador, de uma forma simplificada, como uma mquina capaz
de:
a) avaliar expresses escritas segundo regras sintticas bem definidas,
como a das expresses aritmticas que to bem conhecemos (ex. 3 + 5
- 8) obedecendo semntica das funes primitivas das quais ela
dotada (por exemplo: as funes aritmticas bsicas como somar,
subtrair, multiplicar e dividir);
b) aceitar a definio de novas funes e posteriormente consider-las na
avaliao de expresses submetidas sua avaliao.
Por enquanto, denominaremos o computador de mquina funcional. Na Figura
1.1 apresentamos um exemplo de interao de um usurio com a nossa
Mquina Funcional.
usurio: 3 + 5 / 2
Mquina funcional:: 5,5
usurio: f x y = (x + y) / 2
Mquina funcional: definio de f foi aceita
usurio: (f 3 5) + (f 10 40)
Mquina funcional: 29
Figura 1.1
Na primeira interao podemos observar que o usurio descreveu uma
expresso aritmtica e que a mquina funcional avaliou e informou o resultado.
Na segunda interao o usurio descreve, atravs de uma equao, uma nova
funo, que ele denominou de f e que a mquina funcional acatou a nova
definio. Na terceira interao o usurio solicita a avaliao de uma nova
expresso aritmtica usando o conceito recentemente definido e que a
mquina funcional faz a avaliao usando corretamente o novo conceito. Desta
forma, percebemos que a mquina funcional capaz de avaliar expresses
6
aritmticas e funes e tambm aceitar definies de funes, usando para
isso, ambientes distintos.
1.8. EXPRESSES ARITMTICAS
A nossa mquina funcional hipottica entende a sintaxe das expresses
aritmticas, com as quais todo aluno universitrio j bem familiarizado e
capaz de avali-las usando as mesmas que regras que j conhecemos.
Sintaxe - Todo operador aritmtico pode ser entendido, e aqui o ser,
como uma funo que possui dois parmetros. A notao usual para as
operaes aritmticas a infixada, ou seja, smbolo funcional colocado entre
os dois operandos. Nada impede de pensarmos nelas escritas na forma
prefixada, que a notao usual para funes com nmero de parmetros
diferente de 2. Por exemplo, podemos escrever "+ 3 2" para descrever a soma
do nmero 3 com o nmero 2. As funes definidas pelo programador devem
ser escritas de forma prefixada, como no exemplo de interao apresentado na
Figura 1.1. Combinando essas duas formas, infixada e prefixada, podemos
escrever expresses bastante sofisticadas.
AvaIiao - As expresses aritmticas, como sabemos, so avaliadas de
acordo com regras de avaliao bem definidas, efetuando as operaes de
acordo com suas prioridades. Por exemplo, na expresso "3 + 5 / 2" o primeiro
operador a ser avaliado ser o de diviso (/) e posteriormente o de adio. Se
desejarmos mudar essa ordem, podemos usar parnteses em qualquer
quantidade, desde que balanceados e em posies apropriadas. Por exemplo,
na expresso "(3 + 5) / 2", a utilizao de parnteses determina que a sub-
expresso 3 + 5 ter prioridade na avaliao.
1.9. FUNES
Podemos entender o conceito de funes como uma associao entre
elementos de dois conjuntos A e B de tal forma que para cada elemento de A
existe apenas um elemento de B associado. O conjunto A conhecido como o
domnio da funo, ou ainda como o conjunto de entrada, e o conjunto B o
contra-domnio ou conjunto de sada. Para ser mais preciso, podemos afirmar
que uma funo f , que associa os elementos de um conjunto A aos elementos
de um conjunto B, consiste em um conjunto de pares ordenados onde o
primeiro elemento do par pertence a A o segundo a B. Exemplos:

a) Seja a funo T que associa as vogais do alfabeto com os cinco
primeiros inteiros positivos.
T = {(a,1), (e,2), (i,3), (o,4), (u,5)}
b) Seja a funo Q, que associa a cada nmero natural o seu quadrado.
Q = {(0,0), (1,1), (2,4), (3,9), (4,16), ...}
Podemos observar que a funo T um conjunto finito e que a funo Q
um conjunto infinito.
7
1.10. DESCRIES FUNCIONAIS
Podemos descrever um conjunto, de duas formas: extensional, onde
explicitamos todos os elementos que so membros do conjunto, como no caso
do conjunto T apresentado anteriormente; ou na forma intencional, onde
descrevemos um critrio de pertinncia dos membros do conjunto. Por
exemplo, o conjunto Q acima apresentado poderia ser reescrito da seguinte
forma:
Q = {(x, y) | x naturaI e y = x.x} que pode ser lido da seguinte
maneira:
Q o conjunto dos pares ordenados (x, ) tal que x u! n"!ero
natural e o produto de x por x#
Quando descrevemos uma funo para fins computacionais, estamos
interessados em explicitar como determinar o segundo elemento do par
ordenado, conhecido o primeiro elemento do par. Em outras palavras, como
determinar y conhecendo-se o valor de x. Normalmente dizemos que queremos
determinar y em funo de x. Nesta forma de descrio, omitimos a varivel y e
explicitamos o primeiro elemento que denominado ento de parmetro da
funo. No caso acima teramos ento:
Q x = x . x
1.11. POR QUE COMEAR A APRENDIZAGEM DE PROGRAMAO
ATRAVS DO PARADIGMA FUNCIONAL?
Tendo em vista a prtica vigente de comear o ensino de programao em
cursos de computao utilizando o paradigma procedimental, apresentamos a
seguir alguns elementos que baseiam nossa opo de comear o ensino de
programao usando o paradigma funcional.
1) O aluno de graduao em Computao tem de 4 a 5 anos para
aprender todos os detalhes da rea de computao, portanto no
se justifica que tudo tenha que ser absorvido no primeiro
semestre. O curso introdutrio apenas o primeiro passo e no
visa formar completamente um programador. Este o momento
de apresentar-lhe os fundamentos e, alm disso, permitir que ele
vislumbre a variedade de problemas que podem ser solucionados
como o apoio do computador;
2) O paradigma procedimental requer que o aluno tenha um bom
entendimento dos princpios de funcionamento de um computador
real, pois eles se baseiam, como as mquinas reais, no conceito
de mudana de estados (mquina de Von Neumann).
3) O paradigma lgico, outro forte candidato, requer o conhecimento
de lgica matemtica que o aluno ainda no domina
adequadamente;
4) O paradigma funcional baseado num conhecimento que o aluno
j est familiarizado desde o ensino mdio (funes, mapeamento
entre domnios) o qual ainda explorado em outras disciplinas do
8
ciclo bsico, o que nos permite concentrar nossa ateno na
elaborao de solues e na descrio formal destas;
5) O elevado poder de expresso das linguagens funcionais permite
que a abrangncia do uso do computador seja percebida mais
rapidamente. Em outras palavras, podemos resolver problemas
mais complexos j no primeiro curso;
6) O poder computacional do paradigma funcional idntico ao dos
outros paradigmas. Apesar disso, ele ainda no usado nas
empresas, por vrios aspectos. Dentre os quais podemos citar:
i) No passado, programas escritos em linguagens funcionais
eram executados muito lentamente. Apesar disso no ser
mais verdadeiro, ficou a fama;
ii) A cultura de linguagens procedimentais possui muitos
adeptos no mundo inteiro, o que, inevitavelmente, cria uma
barreira introduo de um novo paradigma. Afinal, temos
medo do desconhecido e trememos quando temos que nos
livrar de algo que j sabemos;
iii) H uma crena que linguagens funcionais so difceis de
aprender e s servem para construir programas de
inteligncia artificial.
7) A ineficincia das linguagens funcionais em comparao s
procedimentais tem se reduzido atravs de alguns mecanismos
tais como: lazy evaluation, grafo de reduo, combinadores.
8) Para fazer um programa que "funciona" (faz alguma coisa,
embora no necessariamente o que desejamos) mais fcil faz-
lo no paradigma procedimental. Para fazer um programa que
funciona "corretamente" para resolver um determinado problema
mais fcil no paradigma funcional, pois esse paradigma
descreve "o que fazer" e no "como fazer".
9) As linguagens funcionais so geralmente utilizadas para
processamento simblico, ou seja, soluo de problemas no
numricos. (Exemplo: integrao simblica X integrao
numrica). Atualmente constata-se um crescimento acentuado do
uso deste tipo de processamento.
10) A crescente difuso do uso do computador nas mais diversas
reas do conhecimento gera um crescimento na demanda de
produo de programas cada vez mais complexos. Os defensores
da programao funcional acreditam que o uso deste paradigma
seja uma boa resposta a este problema, visto que com linguagens
funcionais podemos nos concentrar mais na soluo do problema
do que nos detalhes de um computador especfico, o que
aumenta a produtividade.
11) Se mais nada justificar o aprendizado de uma linguagem
funcional como primeira linguagem, resta a explicao didtica.
Estamos dando um primeiro passo no entendimento de
programao como um todo. , portanto, importante que este
9
passo seja simplificado atravs do apoio em uma "mquina" j
conhecida, como o caso das funes.
12) Ainda um outro argumento: mesmo que tenhamos que usar
posteriormente uma outra linguagem para ter uma implementao
eficiente, podemos usar o paradigma funcional para formalizar a
soluo. Sendo assim, a verso em linguagem funcional poderia
servir como uma especificao do programa.
Exerccios
1. Conceitue programao de computadores.
2. Quais os principais paradigmas de programao e o que os diferenciam.
3. Faa uma descrio intencional da funo: F = {1,3,5,7,...}.
4, Faa uma listagem de outros exemplos de programas de computador que
so usados hoje em diferentes reas do conhecimento e por diferentes
profissionais.
5. Apresente exemplo de outras linguagens tcnicas usadas pelo ser humano
para descrever conhecimento.
6. Os conceitos de correo e de desempenho, se aplicam a qualquer artefato.
Escolha 3 artefatos quaisquer e discuta os dois conceitos.
7. Apresente uma descrio informal da funo que conjuga os verbos
regulares da 1
a
. conjugao.
10
2. A LINGUAGEM DE PROGRAMAO HASKELL E O AMBIENTE HUGS
2.1. INTRODUO
Neste curso usaremos o ambiente HUGS, no qual utilizada uma implementao da
linguagem de programao funcional Haskell. Essa linguagem por apresentar uma sintaxe
simples e elegante, alm de oferecer operadores bastante expressivos, tem sido usada
com bons resultados para a aprendizagem de fundamentos de programao.
Podemos usar o HUGS como uma calculadora qualquer, qual submetemos
expresses que ela avalia e nos informa o valor resultante. Vejamos por exemplo as
interaes a seguir.
? 3 + 5 * 2
13
? (3 + 5) * 2
16
?
Nas expresses acima importante destacar o uso do smbolo * (asterisco) que
empregado para representar a multiplicao. Alm desse, outros smbolos usuais sero
substitudos, como veremos logo mais. As operaes aritmticas so, como sabemos,
funes. A notao utilizada em Haskell para as operaes aritmticas a usual, ou seja,
infixada (o smbolo da operao fica entre os operandos). Uma outra forma existente em
Haskell para escrever expresses usando o operador de forma prefixada. Por exemplo,a
expresso di$ %5 & , indica a diviso inteira do nmero 15 (dividendo) pelo nmero 6
(divisor).
No ambiente HUGS, o smbolo ' usado para indicar que o sistema est preparado
para avaliar uma nova expresso. Aps avaliar uma expresso o resultado informado na
linha seguinte e em seguida uma nova interrogao exibida, se disponibilizando para
uma nova avaliao. O avaliador de expresses do ambiente HUGS funciona conforme o
esquema da figura 2.1. Repetidamente o ambiente HUGS permite a leitura de uma
expresso, sua avaliao e exibio do resultado.
Figura 2.1
Podemos usar o ambiente HUGS somente para isso, para escrever expresses e
solicitar ao sistema que as avalie. Entretanto podemos ousar mais e usar o ambiente para
descrever novas funes a partir das funes j oferecidas pelo ambiente. As funes j
oferecidas pelo ambiente so conhecidas como primitivas. Podemos tambm utilizar
nessas novas definies de funes aquelas que tivermos construdo anteriomente.
2.2. DESCRIO DE FUNES
A forma de descrever funes similar ao que nos referimos anteriormente no Captulo 1,
ou seja, atravs de uma equao, onde no lado esquerdo da igualdade definimos um nome
para a funo e relacionamos os parmetros (ou argumentos) considerados na sua
definio. No lado direito escrevemos uma expresso utilizando outras funes, primitivas
ou no. sto nos leva portanto a tomar conhecimento que a linguagem possui funes
primitivas que j a acompanham e que portanto prescindem de definio.
Por exemplo, para definir a funo que determina o espao percorrido por um mvel
em movimento retilneo uniforme, conhecidos a sua velocidade e o tempo decorrido,
podemos escrever:
espaco $ t ( $ ) t
No esquema a seguir fazemos uma identificao didtica dos vrios elementos da
definio. O lado esquerdo da igualdade tambm chamado de inteface ou assinatura da
funo e o lado direito o corpo da definio.
espaco v t = v * t
nome da
funo
parmetros
expresso aritmtica que define a
relao que h entre os parmetros
interface da funo corpo da definio
Para alimentar o HUGS com novas definies devemos criar um arquivo texto em
disco no qual editaremos as definies desejadas. Cada arquivo pode ter uma ou mais
definies de funes. Normalmente agrupamos em um mesmo arquivo as definies
relacionadas com a soluo de um problema especfico ou definies de propsito geral.
No jargo de programao com a linguagem Haskell, um conjunto de definies
denominado script.
A alimentao de novas definies indicada ao sistema atravs de um comando
que usado no lugar de uma expresso, quando o sistema exibe o seu pedido de tarefa (o
smbolo de interrogao). Para indicar que estaremos executando um comando, usamos o
smbolo " : " (dois pontos) seguido do nome do comando (existem vrios). Para a tarefa
que temos neste instante utilizamos o comando load (oportunamente veremos outros).
Por exemplo, podemos escrever um conjunto de definies em um arquivo
denominado pf001.hs. Para alimentar este arquivo no ambiente HUGS (interpretador)
podemos escrever:
> :Ioad pf001.hs
A partir deste momento, todas as definies contidas no arquivo informado estaro
disponveis para uso. sso pode ser entendido como uma extenso da mquina Haskell. Na
Figura 2.2 apresentamos um esquema de utilizao do ambiente HUGS e de um editor de
textos para provimento de novas definies.
12
Figura 2.2 nteraes do Programador com o Ambiente de Programao
Vale aqui um pequeno lembrete, podemos estender a noo de funes para
incorporar tambm as chamadas funes constantes. Na nomenclatura de definies de
funes, dizemos que temos definies paramtricas e definies no paramtricas.
Por exemplo, podemos definir a constante pi, da seguinte maneira:
pi = 3.1416
A constante pi pode ser entendida como uma funo no paramtrica.
2.3. UM EXEMPLO
Considere que queremos descrever uma funo para determinar as razes de uma
equao do segundo grau.Sabemos que pela nossa clssica frmula as razes so
descritas genericamente por:
A soluo, como sabemos, formada por um par de valores. Por enquanto vamos
descrever este fato por duas funes, uma para a primeira raiz e outra para a segunda.
eq2g1 a b c = ((-b) + sqrt (b^2 - 4! " a " c )) # (2! " a)
Vamos discutir alguns detalhes desta codificao:
13
Editor de
texto
Arquivo texto
com definies
de funes
Ambiente
HUGS
(interpretador)
Programador
o termo *+ precisa ser codificado entre parntesis pois nmeros negativos so
obtidos por um operao unria que produz um nmero negativo a partir de um
positivo;
o smbolo da raiz quadrada foi substitudo pela funo sqrt;
o numerador da frao precisa ser delimitado pelo uso de parntesis;
o denominador tambm precisa ser delimitado por parntesis;
o smbolo de multiplicao usual foi trocado pelo * (asterisco);
o smbolo de potenciao foi substitudo pelo ^ (circunflexo).
Podemos agora descrever a outra raiz de forma anloga:
eq2g2 a b c = ((-b) - sqrt (b^2 - 4! " a " c )) # (2! " a)
Visto que as duas descries possuem partes comuns, poderamos ter escrito
abstraes auxiliares e produzir um conjunto de definies, tal como:
quad x = x " x
raizdelta a b c = sqrt ( quad b - 4! " a " c )
dobro x = 2! " x
eq2g1 a b c = ((-b) + rai$delta a b c) # dobro a
eq2g2 a b c = ((-b) - rai$delta a b c) # dobro a

Vejamos como ficaria uma interao com o HUGS, a partir de um arquivo de
definies denominado eq2g.hs:
% :l eq2g&s
'eading script file (eq2g&s()
*as+ell session for)
standardprelude
eq2g&s
> eq2g1 2.0 5.0 2.0
-0.5
> eq2g2 2.0 5.0 2.0
-2.0
> eq2g1 3.0 4.0 5.0
,rogram error) -sqrt (-44!).
Podemos observar que houve um problema com a avaliao da expresso
eq2,% 3#- .#- 5#-
/ste u! erro se!0ntico, pro$ocado pela tentati$a de extrair a rai1 quadrada
de u! n"!ero ne,ati$o# 2 fun34o que defini!os portanto u!a fun34o parcial, ou
14
seja, ela n4o est definida para todo o do!5nio dos reais# 6este caso o siste!a
apenas acusa o pro+le!a ocorrido#
2.4. DEFINIES LOCAIS
As definies que discutimos anteriormente so globais, no sentido de que esto
acessveis ao uso direto do usurio e tambm disponveis para uso em qualquer outra
definio. Por exemplo, se temos o script
quad x = x * x
hipo x y = sqrt ( quad x + quad y)
podemos utilizar a definio quad tanto externamente pelo usurio quanto internamente
pela definio 7ipo.
Se no entanto desejamos construir subdefinies para uso em uma definio
especfica, podemos defin-las internamente, restringindo o seu contexto. A maneira de
introduzir definies locais em Haskell por meio da clusula 87ere# Vamos modificar o
script acima para que quad s possa ser usado no interior de 7ipo.
hipo x y = sqrt ( quad x + quad y)
where
quad x = x * x

As definies internas tambm no precisam ser paramtricas. Veja este outro
exemplo.
hipo x y = sqrt ( k1 + k2)
where

k1 = x * x
k2 = y * y

Note que apesar de x e no serem parmetros de 9% e 92 eles foram utilizados em
suas definies. sto possvel porque x e tm validade em todo o lado direito da
definio.
Temos que considerar ainda que nada impede que em uma definio local tenhamos
uma outra definio local e dentro desta outra, e assim sucessivamente.
hipo x y = sqrt k
where
k = quad x + quad y
where
quad x = x * x

2.5. MODELO DE AVALIAO DE EXPRESSES: Quando o avaliador (interpretador) do
HUGS toma uma expresso contendo apenas constantes e operaes primitivas, ele
apenas efetua as operaes obedecendo prioridade dos operadores e aquelas
determinadas pelo uso de parntesis. Por exemplo, para avaliar a expresso 3 + 5 / 2,
15
primeiro realizada a diviso 5/2, resultando em 2.5, o qual adicionado ao 3, finalmente
obtendo 5.5. Podemos entender isso como uma seqncia de redues de uma expresso
outra mais simples, at que se atinja um termo irredutvel.
Veja os exemplos a seguir:
3 + 5 / 2 3 + 2.5 5.5
(3 + 5) / 2 8 / 2 4
3 + 5 + 2 8 + 2 10
As setas () so usadas para indicar um passo de reduo.
Quando as expresses utilizam funes definidas pelo usurio, o processo anlogo.
Cada referncia a uma definio substituda por seu lado direito, at que se atinja uma
expresso bsica, e prossegue como no caso anterior. Vejamos os exemplos abaixo,
considerando a primeira definio de 7ipo e de quad apresentada anteriormente:

ordem expresso
reduo
aplicada
1 hipo 3 5 + hipo 4 4
expresso
inicial
2 sqrt ( quad 3 + quad 5) + hipo 4 4 def de hipo
3 sqrt ( 3 * 3 + quad 5) + hipo 4 4
def de
quad
4 sqrt (3 * 3 + 5 * 5) + hipo 4 4
def de
quad
5 sqrt (3 * 3 + 5 * 5) + sqrt (quad 4 + quad 4) def de hipo
6 sqrt (3 * 3 + 5 * 5) + sqrt (4 * 4 + quad 4)
def de
quad
7 sqrt (3 * 3 + 5 * 5) + sqrt (4 * 4 + 4 * 4)
def de
quad
8 sqrt (9 + 5 * 5) + sqrt (4 * 4 + 4 * 4) *
9 sqrt (9 + 25) + sqrt (4 * 4 + 4 * 4) *
10 sqrt 34 + sqrt (4 * 4 + 4 * 4) +
11 5.83095 + sqrt (4 * 4 + 4 * 4) sqrt
12 5.83095 + sqrt (16 + 4 * 4) *
13 5.83095 + sqrt (16 + 16) *
14 5.83095 + sqrt (32) +
15 5.83095 + 5.65685 sqrt
16 11.4878 +

Para uma realizao especfica da linguagem, isso no precisa acontecer exatamente
assim. Entretanto este modelo suficiente para nossos interesses. O nmero de redues
necessrias para chegar forma irredutvel de uma expresso, tambm denominada de
forma cannica ou ainda forma normal, pode ser usado como critrio para discutir o
desempenho da mesma.
Exerccios
16
1. Estabelea categorias para comparar duas definies;
2. Usando as categorias definidas no item 1 compare as duas definies apresentadas
para as razes de uma equao do segundo grau;
3. Compare usando as suas categorias, as trs definies apresentadas para hipo;
4. Apresente uma explicao para o erro produzido pela avaliao da expresso
eq2,% 3#- .#- 5#-
5. Apresente uma seqncia de redues para a expresso:
eq2,% 2#- 5#- 2#-
6. Apresente um conjunto de definies para a funo total para a determinao das
razes de uma equao do segundo grau.
2.6. ASSINATURA DE FUNES E A NOTAO CURRY:
Do estudo de funes sabemos que toda funo possui um domnio e um contradomnio.
O domnio pode ser formado por zero ou mais conjuntos. Quando uma funo no possui
domnio dizemos que uma funo constante. Para descrever este conhecimento sobre
domnio e contradomnio usado o conceito de "assinatura, do ingls "signature.
Para conhecer o tipo de uma funo, disponvel na biblioteca do HUGS ou construda
pelo programador, basta usar, no ambiente HUGS, o comando:
Hugs> :t <nome da funo>
O quadro a seguir apresenta alguns exemplos.
Hugs> :t sqrt
sqrt :: Floating a => a -> a
Hugs> :t sin
sin :: Floating a => a -> a
Hugs> :t abs
abs :: Num a => a -> a
Hugs> :t mod
mod :: Integral a => a -> a -> a
Hugs> :t div
div :: Integral a => a -> a -> a
O exemplo sqrt :: Floating a => a -> a, pode ser lido da seguinte maneira:
"A funo sqrt mapeia um valor a do tipo FIoating em outro valor do tipo FIoating.
Os termos :nte,ral, :nt, 6u!, ;loatin, etc sero cuidadosamente apresentados no
Capitulo 5. Por enquanto, basta antecipar que cada valor, inclusive os numricos, podem
ser de tipos diferentes e a linguagem prov uma classificao para esses valores.
Podemos fazer uma analogia com a matemtica clssica onde os nmeros podem ser:
naturais, inteiros, racionais, reais, irracionais, co!plexos etc. As linguagem de
programao, por questes relacionadas com a tecnologia digital, podem "inventar outros
tipos para facilitar a manipulao de dados pelos computadores digitais.
17
Vejamos um exemplo: na funo que determina a mdia aritmtica de 3 nmeros reais,
temos que o domnio formado pelo produto cartesiano R x R X R e o contradomnio
R.
A assinatura desta funo a seguinte:
ma3 :: R X R X R R
Em Haskell poderamos ter a seguinte definio:
ma3 x y z = (x + y + z) / 3.
usual tambm dizer que R X R X R R o tipo da funo !a3.
Para simplificar o trabalho com funes o matemtico Haskell Curry criou uma nova
notao, que considera que qualquer funo tem sempre um nico parmetro de entrada.
Segundo ele, o resultado de aplicar uma funo sobre um parmetro produz uma nova
funo que pode ser aplicada a outro parmetro, e assim sucessivamente. Por exemplo,
nesta notao, a funo !a3 teria a seguinte assinatura:
ma3 :: R R R R
Podemos ler da seguinte maneira: !a3 uma funo que mapeia um numero real em uma
nova funo cuja assinatura :
ma3 :: R R R.
A funo ma3 por sua vez mapeia um nmero real em uma nova funo cuja assinatura
:
ma3 :: R R.
A funo ma3 por sua vez mapeia um nmero real em uma nova funo cuja
assinatura :
ma3 :: R.
Que uma funo constante.
No exemplo acima, quando solicitamos a avaliao da expresso: ma3 3 4 5
o processo de avaliao pode ser entendido da seguinte maneira:
ma3 3 4 5
"(x + y + z)/ 3 4 5
18
"( 3 + y + z)/ 3 4 5
"(3 + 4 + z)/3 5
"(3 + 4 + 5)/3
"(7 + 5)/3
"12/3
4
Podemos ainda, obter a definio de novas funes a partir de uma funo f previamente
definida.
f x y z = x + y + z
g x y = f 3 x y
h x = g 4 x
m = h 5
No quadro a seguir mostramos a avaliao de tipos de cada uma das funes.
Main> :t f
f :: Num a => a -> a -> a -> a
Main> :t g
g :: Num a => a -> a -> a
Main> :t h
h :: Num a => a -> a
Main> :t m
m :: Integer
Vejamos agora uma avaliao de expresses com estas funes:
Main> (f 10 20 30) + (g 20 30) + (h 30) + m
162
Main> g 20 30
53
Main> f 10 20 30
60
Main> g 20 30
53
Main> h 30
37
Main> m
12
Exerccios
1) Avalie as expresses abaixo e apresente a sequncia de redues necessrias
para a obteno do termo irredutvel (resultado final):
a. mod 15 2
b. mod 15 2 + div 6 3
c. ma3 5 10 2
19
d. sqrt (15 2*3) / (17 12)
2) Escreva um arquivo texto (script) contendo a definio das funes abaixo. Use,
quando for adequado, definies locais:
a. Determinao da rea de um retngulo de lados a e b
b. Determinao da rea de um crculo de raio r
c. Determinao da mdia aritmtica de trs nmeros a, b e c
3. A ARTE DE RESOLVER PROBLEMAS
3.1. INTRODUO
O grande objetivo deste curso criar oportunidades para que o estudante desenvolva suas
habilidades como resolvedor de problemas. Mais especificamente estamos interessados
na resoluo de problemas usando o computador, entretanto, temos certeza, que as idias
so gerais o suficiente para ajudar a resolver qualquer problema.
Embora muitas pessoas j tenham discutido sobre este assunto ao longo da histria,
nosso principal referencial ser o professor George Polya, que escreveu um livro sobre
este assunto, com o mesmo nome deste captulo, voltado para a resoluo de problemas
de matemtica do ensino fundamental. Todos os alunos deste curso tero grande proveito
se lerem este livro.
As idias ali apresentadas com certeza se aplicam com muita propriedade
resoluo de problemas com o computador. Na medida do possvel estaremos
apresentando aqui algumas adaptaes que nos parecem apropriadas neste primeiro
contato com a resoluo de problemas usando o computador.
3.2. DICAS INICIAIS
Apresenta-se a seguir algumas orientaes:
3.2.1. S se aprende a resolver problemas atravs da experincia. Logo o aluno que
est interessado em aprender deve trabalhar, buscando resolver por si mesmo, os
problemas propostos antes de tentar o auxlio do professor ou de outro colega;
3.2.2. A ajuda do professor no deve vir atravs da apresentao pura e simples de
uma soluo. A ajuda deve vir atravs do fornecimento de pistas que ajudem o aluno a
descobrir a soluo por si mesmo;
3.2.3. muito importante no se conformar com uma nica soluo. Quanto mais
solues encontrar, mais hbil o estudante ficar, e alm disso, poder comparar as vrias
alternativas e escolher a que lhe parecer mais apropriada. A escolha dever sempre ser
baseada em critrios objetivos.
3.2.4. Na busca pela soluo de um problema, nossa ferramenta principal o
questionamento. Devemos buscar formular questes que nos ajudem a entender o
problema e a elaborar a soluo.
3.2.5. Aprenda desde cedo a buscar um aprimoramento da sua tcnica para resolver
problemas, crie uma sistematizao, evite chegar na frente de um problema como se
nunca tivesse resolvido qualquer outro problema. Construa um processo individual e v
aperfeioando-o cada vez que resolver um novo problema.
20
3.3 COMO RESOLVER UM PROBLEMA
O professor Polya descreve a resoluo de um problema como um processo complexo que
se divide em quatro etapas, as quais apresentamos aqui, com alguma adaptao. Segundo
nos recomenda Polya, em qualquer destas etapas devemos ter em mente trs questes
sobre o andamento do nosso trabalho, que so: Por onde comear esta etapa? O que
posso fazer com os elementos que disponho? Qual a vantagem de proceder da forma
escolhida?
Etapa 1 - Compreenso do ProbIema
impossvel resolver um problema sobre o qual no tenhamos um entendimento
adequado. Portanto, antes de correr atrs de uma soluo, concentre-se um pouco em
identificar os elementos do problema. Faa perguntas tais como: Quais so os dados de
entrada? O que desejamos produzir como resultado? Qual a relao que existe entre os
dados de entrada e o resultado a ser produzido? Quais so as propriedades importantes
que os dados de entrada possuem?
Etapa 2 - PIanejamento
Nesta fase devemos nos envolver com a busca de uma soluo para o problema
proposto. Pode ser que j o tenhamos resolvido antes, para dados ligeiramente
modificados. Se no o caso, pode ser que j tenhamos resolvido um problema parecido.
Qual a relao que existe entre este problema que temos e um outro problema j
conhecido? Ser que podemos quebrar o problema em problemas menores? Ser que
generalizando o problema no chegaremos a um outro j conhecido? Conhecemos um
problema parecido, embora mais simples, o qual quando generalizado se aproxima do que
temos?
Etapa 3 - DesenvoIvimento
Escolhida uma estratgia para atacar o problema, devemos ento caminhar para a
construo da soluo. Nesta fase, devemos considerar os elementos da linguagem de
programao que iremos usar, respeitando os elementos disponibilizados pela linguagem,
tais como tipos, formas de definio, possibilidades de generalizao e uso de elementos
anteriormente definidos. A seguir, devemos codificar cada pedao da soluo, e garantir
que cada um esteja descrito de forma apropriada. Em outras palavras, no basta construir,
temos que ser capazes de verificar se o resultado de nossa construo est correto. sto
pode ser realizado pela identificao de instncias tpicas, da determinao dos valores
esperados por estas, da submisso dessas instncias ao avaliador e finalmente, da
comparao dos resultados esperados com os resultados produzidos pela avaliao de
nossas definies. Alm disso, devemos garantir que a definio principal tambm est
correta.
Em sntese, a fase de desenvolvimento compreende as seguintes subfases:
1. construo da soluo;
2. planejamento do teste;
3. execuo manual do teste;
21
4. codificao da soluo;
5. teste com o uso do computador.
Etapa 4 - AvaIiao do Processo e seus resuItados
O trabalho do resolvedor de problemas no pra quando uma soluo est pronta.
Devemos avaliar a qualidade da soluo, o processo que realizamos e questionar as
possibilidades de uso posterior da soluo obtida e tambm do prprio mtodo utilizado.
Novamente devemos fazer perguntas: Este foi o melhor caminho que poderia ter sido
usado? Ser que desdobrando a soluo no obtenho componentes que poderei usar mais
facilmente no futuro? Se esta soluo for generalizada possvel reus-la mais facilmente
em outras situaes? Registre tudo, organize-se para a resoluo de outros problemas.
Anote suas decises, enriquea a sua biblioteca de solues e mtodos.
3.4. UM PEQUENO EXEMPLO
Enunciado: Deseja-se escrever um programa que permita determinar a menor quantidade
de cdulas necessrias para pagar uma dada quantia em Reais.
Etapa 1 - Compreenso
Questo: Quais os dados de entrada?
Resposta: A quantia a ser paga.
Questo: Qual o resultado a ser obtido?
Resposta: A menor quantidade de cdulas.
Questo: Qual a relao que existe entre a entrada e a sada?
Resposta: O somatrio dos valores de cada cdula utilizada deve ser igual quantia
a ser paga.
Questo: Existe algum elemento interno, ou seja, uma dado implcito?Resposta: Sim,
os tipos de cdulas existentes.Considere que o Real possui apenas as seguintes
cdulas: 1, 5, 10, 50 e 100. importante observar que qualquer cdula um mltiplo
de qualquer uma das menores.
Etapa 2 - PIanejamento
Conheo algum problema parecido? Existe um problema mais simples?
Podemos entender como um problema mais simples um que busque determinar
quantas cdulas de um dado valor so necessrias para pagar a quantia desejada.
Por exemplo, para pagar R$ 289,00 poderamos usar 289 cdulas de R$ 1,00. Ou
tambm poderamos usar 5 notas de R$ 50,00, mas neste caso ficariam ainda
faltando R$ 39,00. Claro que no queremos que falte nem que sobre e, alm disso,
22
desejamos que a quantidade seja mnima. Parece uma boa estratgia comear
vendo o que d para pagar com a maior cdula e determinar quando falta pagar. O
restante pode ser pago com uma cdula menor, e por a afora. Explorando a instncia
do problema j mencionada, vamos fazer uma tabela com estes elementos.
Expresso para
determinar a
quantidade de
cdulas de um
determinado
valor.
Quantidade
de cdulas
Quantia a Pagar
289,00
289 / 100 2 89,00
89/ 50 1 39,00
39/ 10 3 9,00
9/ 5 1 4,00
4/ 1 4 0,00
TOTAL 11

Etapa 3 - DesenvoIvimento
Soluo 1 - Considerando a tabela acima descrita, codificando cada linha como uma
subexpresso da definio.
ncedulas q = (div q 100) +
(div (mod q 100) 50) +
(div (mod (mod q 100) 50) 10) +
(div (mod (mod (mod q 100) 50) 10) 5)+
(div (mod (mod (mod (mod q 100) 50) 10) 5) 1)
Soluo 2 - Considerando uma propriedade das cdulas, ou seja, j que uma cdula
qualquer mltiplo das menores, a determinao do resto no precisa considerar as
cdulas maiores do que a cdula que estamos considerando em um dado ponto.
ncedulas2 q = (div q 100) +
(div (mod q 100) 50) +
(div (mod q 50) 10) +
(div (mod q 10) 5)+
(div (mod q 5) 1)
23
Etapa 4 - AvaIiao
A soluo deixa de explicitar as abstraes referentes quantidade de cdulas de um
determinado valor, assim como o resto correspondente. Podemos questionar, no seria
melhor explicitar? Assim poderamos us-las de forma independente e alm disso, a
soluo fica mais clara e portanto inteligvel.
ncedulas q = n100 q + n50 q + n10 q + n5 q + n1 q
n100 q = div q 100
r100 q = mod q 100
n50 q = div (r100 q) 50
r50 q = mod (r100 q) 50
n10 q = div (r50 q) 10
r10 q = mod (r50 q) 10
n5 q = div (r10 q) 5
r5 q = mod (r10 q) 5
n1 q = div (r10 q) 5
Supondo que no queremos generalizar todas as funes menores ainda poderamos
escrever o programa usando definies locais.
ncedulas q = n100 + n50 + n10 + n5 + n1
where

n100 = div q 100
r100 = mod q 100
n50 = div r100 50
r50 = mod r100 50
n10 = div r50 10
r10 = mod r50 10
n5 = div r10 5
n1 = mod r10 5

Podemos ainda considerar que se houver uma troca no sistema, de modo a incluir
uma nova cdula que no seja mltiplo de seus valores menores. Seria fcil mudar o
programa para contemplar a mudana nas leis do mundo do problema.
3.5. PROVRBIOS
O professor Polya tambm nos sugere que a lembrana de alguns provrbios pode ajudar
o aprendiz (e o resolvedor de problemas) a organizar o seu trabalho. Diz Polya que, apesar
dos provrbios no se constiturem em fonte de sabedoria universalmente aplicvel, seria
uma pena desprezar a descrio pitoresca dos mtodos heursticos que apresentam.
Alguns so de ordem geral, tais como:
/ fim indica os meios
24
0eus mel&ores amigos so / que1 ,or que1 /nde1 2uando e 3omo pergunte / que1
pergunte ,or que1 pergunte /nde1 pergunte 2uando e pergunte 3omo - e no pergunte a
ningu4m quando precisar de consel&o
5o confie em coisa alguma1 mas s6 du7ide daquilo que merecer d87ida
/l&e em torno quando encontrar o primeiro cogumelo ou fi$er a primeira descoberta9
ambos surgem em grupos

A seguir apresentamos uma lista deles, organizados pelas etapas s quais parecem
mais relacionados.
Etapa 1 : Compreenso do probIema.
2uem entende mal1 mal responde
,ense no fim antes de comear
/ tolo ol&a para o comeo1 o s:bio 7; o fim
/ s:bio comea pelo fim1 o tolo termina no comeo
Etapa 2 : PIanejamento da soIuo.
< perse7erana 4 a me da boa sorte
5o se derruba um car7al&o com uma s6 mac&adada
0e no princ=pio no conseguir1 continue tentando
>xperimente todas as c&a7es do mol&o
?ele@a-se conforme o 7ento
Aaamos como pudermos se no pudermos fa$er como queremos
/ s:bio muda de opinio1 o tolo nunca
Banten&a duas cordas para um arco
Aaa e refaa que o dia 4 bastante longo
/ ob@eti7o da pescaria no 4 lanar o an$ol mas sim pegar o peixe
/ s:bio cria mais oportunidades do que as encontra
/ s:bio fa$ ferramentas daquilo que l&e cai Cs mos
Aique sempre de ol&o na grande ocasio
Etapa 3: Construo da soIuo.
/l&e antes de saltar
,ro7e antes de confiar
Dma demora prudente torna o camin&o seguro
2uem quiser na7egar sem risco1 no se faa ao mar
Aaa o que puder e espere pelo mel&or
E f:cil acreditar naquilo que se dese@a
25
Fegrau a degrau sobe-se a escada
/ que o tolo fa$ no fim1 o s:bio fa$ no princ=pio
Etapa 4: AvaIiao da soIuo.
5o pensa bem quem no repensa
E mais seguro ancorar com dois ferros
Exerccios
1) Compare as duas definies para a funo que descreve o nmero mnimo
de cdulas para pagar uma quantia q, ncedulas e ncedulas2. Discuta;
2) Desenvolva a soluo para o problema da cdulas considerando o fato de
que o Real possui notas de 2 e notas de 20. O que muda?
3) Apresente trs problemas semelhante ao das cdulas;
4) Desenvolva uma soluo para o problema considerando que para cada tipo
de cdula existe um quantidade limitada (maior ou igual a zero);
26
4. ABSTRAO, GENERALIZAO, INSTANCIAO E MODULARIZAO
4.1. INTRODUO
Na busca por resolver um problema podemos usar vrios princpios, cada um
evidentemente ter uma utilidade para a resoluo do problema, ou para garantia de sua
correo ou ainda para facilitar os usos posteriores da soluo que obtivermos.
Apresentamos a seguir alguns deles.
4.2. ABSTRAO
Quando escrevemos uma expresso e no damos nome a ela, o seu uso fica limitado
quele instante especfico. Por exemplo, suponha que desejamos determinar a hipotenusa
de um tringulo retngulo com catetos 10 e 4. Como conhecemos o teorema de Pitgoras
(a
2
= b
2
+ c
2
), podemos usar diretamente nossa mquina funcional para avaliar a seguinte
expresso:

> sqrt ((10.0 * 10.0)+ (4.0 * 4.0))
10.7703
A expresso que codificamos serve apenas para esta vez. Se em algum outro
instante precisarmos avali-la, teremos que codific-la novamente.
Para evitar isso, que damos nomes s nossas expresses, para que possamos us-
las repetidamente, apenas referenciando-as pelo seu nome. No caso acima, poderamos
escrever a definio:
hipotenusa = sqrt ((10.0 * 10.0)+ (4.0 * 4.0))
De posse dessa definio nossa mquina poder avaliar a expresso sempre que
dela precisarmos. Basta escrev-la:
> hipotenusa
10.7703
Voc pode agora estar se perguntando, porque no trocamos a definio para usar
diretamente o valor %-#<<-3?
hipotenusa = %-#<<-3
Agindo assim a mquina no precisaria avaliar a expresso sqrt ((%-#- ) %-#-)+ (.#- )
.#-)) a cada uso. Por outro lado no ficaria registrada a origem do valor %-#<<-3, com o
tempo perderamos esta informao. De qualquer forma, teramos criado uma abstrao
qual denominamos 7ipotenusa.
Outra pergunta pode estar rondando a sua cabea, por que escrever uma definio
que sempre avaliada para o mesmo valor, por que no generaliz-la? Bom, este foi
apenas um recurso didtico para separar os dois conceitos: a abstrao que acabamos de
apresentar e a generalizao que apresentaremos a seguir. No entanto convm lembrar
que algumas definies so realmente constantes e que so de grande utilidade, como
o caso da seguinte definio:
27
pi = 3.1416
4.3. GENERALIZAO
Quando uma abstrao se aplica a vrios valores podemos generaliz-la. Assim, alm de
us-la vrias vezes para os mesmos valores, podemos tambm us-la para valores
diferentes. Esta ultima alternativa evidentemente facilita o seu reuso.
Vamos apresentar duas formas para fazer isso:
a) Elaborando a definio usando outras definies constantes. Por exemplo, no caso
da definio acima para a hipotenusa, poderamos escrever as definies a seguir:
b = 10.0
c = 4.0
hipotenusa = sqrt (( b * b) + ( c * c))
Aqui, 7ipo se aplica a dois valores quaisquer + e c, os quais so objetos de outras
definies.
b)Uma forma mais geral atravs do conceito de parametrizao. Esta consiste em
indicar no cabealho da definio (lado esquerdo da igualdade) quais so os objetos da
generalizao. Para o exemplo que estamos trabalhando, podemos escrever:
hipotenusa b c = sqrt (( b * b) + ( c * c))
Temos ento descrito a funo paramtrica 7ipotenusa cujos parmetros so + e c.
4.4 INSTANCIAO
A parametrizao permite que usemos a mesma definio para diferentes instncias do
problema. Por exemplo, suponha que desejamos determinar a hipotenusa de trs
tringulos retngulos. O primeiro com catetos 10 e 4, o segundo com catetos 35 e 18 e o
terceiro com catetos 9 e 12. Podemos instanciar a definio paramtrica para estabelecer
a seguinte interao:
> hipo 10.0 4.0
10.7703
> hipo 35.0 18.0
39.3573
> hipo 9.0 12.0
15.0
4.5. MODULARIZAO
Em geral, nossos problemas no sero to simples e diretos quanto o exemplo acima.
Quando nos deparamos com problemas maiores, um bom princpio :
=i$ida para facilitar a conquista#
Basicamente este princpio consiste em quebrar o problema inicial em problemas
menores, elaborar a soluo para cada um dos problemas menores e depois combin-las
para obter a soluo do problema inicial. A cada um dos subproblemas encontrados
28
podemos reaplicar o mesmo princpio. Segundo Polya, esta uma heurstica muito
importante qual ele denomina de Decomposio e Combinao. Antes de pensar em
codificar a soluo em uma linguagem de programao especfica, podemos represent-la
atravs de um esquema grfico denominado de estrutura modular do problema (veja a
representao para o exemplo a seguir).
4.5.1 MODULARIZANDO: Considere o problema de descrever a rea da Figura 4.1
abaixo.
Figura 4.1 Um polgono irregular para o qual desejamos
determinar a sua rea
Como podemos concluir por uma inspeo da figura, no existe uma frmula pronta
para calcular sua rea. Precisamos dividir a figura em partes para as quais conheamos
uma maneira de calcular a rea e que, alm disso, conheamos as dimenses
necessrias.
Podemos fazer vrias tentativas, como por exemplo, as ilustradas nas Figuras 4.2 a,
4.2 b e 4.2 c.
29
a b c
Figura 4.2 Possveis subdivises do polgono
apresentado na Figura 4.1.
Podemos tentar descrever a rea das figuras menores em cada uma das figuras
apresentadas. Nas Figuras 4.2.b e 4.2c, parece que precisaremos subdividir novamente.
Em 4.2 b a "casinha pode ser transformada em um retngulo e um tringulo. Em 4.2 c a
"casinha azul (meia-gua) que pode ser dividida em um retngulo e um tringulo, como na
Figura 4.3. E a Figura 4 a? Que podemos dizer?
Figura 4.3 Subdiviso de uma sub!igura da Figura
4.3 "#
Vamos partir para a nossa soluo a partir da figura Fig. 4.2c. Podemos dizer que a
rea total pode ser obtida pela soma das reas amarela, vermelha e azul. A rea azul pode
ser subdividida em azul-claro e azul-escuro (ver Figura 4.3).

rea total = rea amarela + rea vermelha + rea azul
rea azul = rea azulclaro + rea azulescuro

Quando escolhemos as reas acima citadas, no foi por acaso. A escolha foi
baseada na simplicidade do subproblema. Podemos usar este conhecimento para chegar a
um outro. Trs das reas que precisamos calcular so de forma retangular. Ou seja, so
especializaes de um conceito mais geral. A quarta rea, tambm pode ser obtida pela
especializao do conceito de tringulo retngulo.
Vamos agora aproximar nossas definies da linguagem de programao.
Portanto podemos escrever:
30
a_retanguIo x y = x * y
O tringulo que temos retngulo e podemos descrever sua rea por:
a_t_retanguIo x y = (x * y) / 2.0
A determinao da rea vermelha nos traz uma pequena dificuldade. No nos foi
informado qual o comprimento da base do retngulo. E agora? Observando bem a figura
podemos concluir que a base do retngulo igual hipotenusa do tringulo retngulo de
catetos a e d# Podemos escrever ento:
atotal a b c d e = a_retangulo a b + a_retangulo (hipo a d) e + a_azul a c d
a_azul x y z = a_retangulo y z + a_t_retangulo x y
hipo x y = sqrt ( x * x + y * y)
a_retangulo x y = x * y
a_t_retangulo x y = (x * y) / 2.0

A estrutura da soluo de um problema obtida pela modularizao pode ser
representada por um diagrama denominado rvore. Para o problema acima discutido a
rvore da forma apresentada na Figura 4.5.
Figura 4.5 Representao em rvore da estrutura modular do problema "clculo
da rea do polgono irregular apresentado na Figura 4.1.
4.6. UM EXEMPLO DETALHADO
Problema: Escreva uma descrio funcional para o volume de cada uma das peas
apresentadas nas Figuras 4.6 e 4.7.
31
Figura 4.$ %e&a no. 1 Figura 4.' %e&a no. (
SoIuo 1: Vamos comear pela Figura 4.6. Uma rpida anlise nos leva a identificar
duas partes. Na parte inferior temos um paraleleppedo, sobre o qual se assenta um
cilindro. Vamos supor que so macios. Chamemos de a, b e c as dimenses do
paraleleppedo, de r o raio da base do cilindro e de & a sua altura. O volume total da pea
pode ser determinado pela soma do volume das duas peas menores. Chamemos a
funo de volfig46. Uma possvel definio para essa funo :

voIfig46 a b c r h = (a * b * c) + (3.1416 * r * r * h)
Vamos ento tratar da pea descrita na figura 4.7. Agora identificamos uma pea
apenas. Um paraleleppedo com um furo no centro. Chamemos de a, b e c as dimenses
do paraleleppedo, de r o raio do buraco. Para descrever o volume da pea devemos
subtrair do volume do paraleleppedo o volume correspondente ao buraco. Chamemos a
funo de volfig47. Uma possvel definio para volfig47 :.
voIfig47 a b c r = (a * b * c) - (3.1416 * r * r * c)
SoIuo 2: A soluo 1, apesar de resolver o problema, deixa de contemplar algumas
prticas importantes. No tratamento da primeira pea (Figura 4.6), apesar de identificadas
duas peas menores, estas abstraes no foram descritas separadamente. Ou seja,
deixamos de registrar formalmente a existncia de duas abstraes e com isso no
pudemos modularizar a descrio da funo principal. Podemos tentar ento um outro
caminho, contemplando as abstraes para o cilindro e para o paraleleppedo:
volcil r h = 3.1416 * r * r * h
volpar a b c = a * b * c
Volfig46 a b c r h = volpar a b c + volcil r h
Voltemos ento para a segunda pea (Figura 4.7), e vejamos se podemos identificar
similaridades. Aqui s temos uma pea, que se parece com o paraleleppedo da primeira
figura. Como podemos identificar similaridades? Aprofundando melhor nossa anlise
podemos lembrar que o furo no paraleleppedo, corresponde a um cilindro que foi retirado.
Desta forma, podemos ento concluir que o volume da figura 4.7 pode ser obtido pela
diferena entre o volume de um paraleleppedo e de um cilindro. Como j temos as
definies para volume de cilindro e volume de paraleleppedo, s nos resta escrever a
definio final do volume da figura 4.7:

voIfig47 a b c r = volpar a b c - volcil r c
32
Analisando a soluo, podemos tirar algumas concluses:
a) a soluo ficou mais clara,
b) a soluo propiciou o reaproveitamento de definies.
c) se precisarmos usar volume de cilindro e de paraleleppedo isoladamente ou em
outras combinaes, j as temos disponveis.
Consideraes compIementares - As descries das reas de um retngulo e de
uma circunferncia podem ser dadas respectivamente por:

acir r = pi * r * r
aret a b = a * b
Desta forma, podemos reescrever o volume do cilindro e do paraleleppedo da
seguinte maneira:
volcil r h = acir r * h
volpar a b c = aret a b * c
SoIuo 3: Se aprofundarmos a anlise podemos observar que as duas figuras
podem ser abstradas como uma s! O cilindro que aparece na primeira, como um volume
que deve ser acrescentado pode ser entendido como o mesmo cilindro que deve ser
subtrado na segunda. Alm disso, podemos estender a soluo para furos que no vazem
a pea, pois a altura do cilindro pode ser qualquer. Considere a definio a seguir:

voIfig a b c r h = volpar a b c + volcil r h
Podemos observar que esta a mesma definio apresentada anteriormente para a
Figura 4.6. O que muda o uso. Para calcular o volume da Figura 4.6 usamos um 7
positivo e para Figura 4.7 um 7 negativo. Observe os exemplos a seguir:
> volfig 6.0 8.0 2.0 2.0 5.0
158.832
-- determina o volume de uma instncia da figura
Fig. 4.6, com um cilindro de raio 2 e altura 5.
> volfig 6.0 8.0 2.0 2.0 (-2.0)
70.8673
-- determina o volume de uma instncia da figura
Fig. 4.7, vasada por um furo de raio 2.
-- neste caso fornecemos um valor negativo para
a altura do cilindro com o mesmo valor da altura
do paraleleppedo
> volfig 6.0 8.0 2.0 2.0 (-1.0)
83.4336
-- determina o volume de uma instncia da figura
Fig. 4.7, que tem um furo de raio 2 e
profundidade 1.
33

Exerccios:
1) Discuta o significado da expresso voIfig 6.0 8.0 2.0 2.0 (-5.0). O que poderia
ser feito para contornar este efeito indesejvel?
2) Resolva o problema da Figura 4.1 usando a modularizao sugerida pela
figura 4.2 b.
3) Redesenhe a Figura 4.5 (rvore de modularizao) para a soluo
apresentada ao exerccio 2.
4) Apresente 3 problemas similares para clculo de rea de polgono irregular.
5) Apresente 3 problemas similares para clculo de volume de objetos.
6) Apresente 3 problemas similares em outros domnios de conhecimento.
34
5. TIPOS DE DADOS NUMRICOS
5.1. INTRODUO
Denominamos Tipo de Dados a um conjunto de valores, munido de um conjunto de
operaes sobre esses valores. Por exemplo, podemos denominar de T1 ao tipo de dados
formado por um conjunto S de valores idntico aos nmeros naturais (S = {0,1,2,3, ...}) e
munido das operaes de adio (a) e multiplicao (!). Cada operao possui, por sua
vez, um tipo, indicando o domnio e o contradomnio. Por exemplo, para o tipo T1, o
domnio de a > ? > e o contradomnio ># Como visto anteriormente, a notao a seguir
usualmente utilizada e em geral denominada de "assinatura da operao.
a :: S X S S
m :: S X S S
Como visto no Captulo 2, na notao Curry escreveramos:
a :: S S S
m :: S S S
Em Haskell, conhecendo-se o tipo das operaes e funes que compem uma
expresso podemos determinar o tipo do valor que dela resultar, ou seja, o seu contra-
domnio. Em linguagens de programao isto equivale a dizer que a linguagem
forte!ente tipada. Dizemos ainda que os tipos so elementares ou estruturados. Os
numricos so elementares, assim como tambm o so os tipos lgico e os caracteres.
Neste captulo trataremos dos tipos numricos, os demais viro em captulos posteriores.
Os nmeros formam um tipo de dados fundamental na computao. Aqui nos
interessa subdividi-los em inteiros e reais. Antes de irmos alm, importante que se saiba
que, sendo o computador composto de elementos finitos, algumas adaptaes e
simplificaes precisam ser feitas para o tratamento de nmeros. Em HUGS, quando
estamos submetendo expresses para avaliao, podemos desejar que o tipo do resultado
seja exibido. Para que isso ocorra podemos usar o comando :set, que ativa ou desativa
parmetros do ambiente. Para ativar um parmetro usamos uma letra correspondente ao
parmetro, precedido do smbolo "+. Para desativar usamos o smbolo "-". Para saber
sobre outros parametros, experimente submeter apenas o comando ":set. A seqncia de
interaes a seguir ilustra a ativao e desativao da exibio dos tipos dos resultados
das avaliaes.
> :set +t
> 2^20
1048576 :: Integer
> :set -t
> 2^100
1267650600228229401496703205376
Os parmetros do interpretador, ativados pelo comando :set, so vlidos apenas
enquanto a sesso do HUGS estiver ativa.
35
5.2. NMEROS INTEIROS
Para trabalhar com nmeros inteiros, a linguagem Haskell prov o tipo Integer, que pode
produzir nmeros com uma quantidade ilimitada de algarismos. Entretanto, como a
memria do computador finita, qualquer que seja a mquina real que estivermos usando,
inevitavelmente esbarrar em limites. Na ilustrao a seguir podemos observar essa
flexibilidade, quando obtemos o valor para a expresso 2
1000
, um nmero de 302
algarismos. Claro, o limite pode estar bem longe e podemos no ating-lo em nossas
aplicaes.
> 2^1000
1071508607186267320948425049060001810561404811705533607443750388370351051
1249361224931983788156958581275946729175531468251871452856923140435984577
5746985748039345677748242309854210746050623711418779541821530464749835819
4126739876755916554394607706291457119647768654216766042983165262438683720
5668069376
Experimente com nmeros maiores! Por exemplo, 9999
9999
um nmero que tem por volta
de 40 mil algarismos. provida ainda uma representao de inteiros mais restrita,
denominada :nt. Esta verso trabalha com um intervalo de valores fixo e reduzido e tem
como vantagem economizar memria do computador e tempo de processamento, usando
caractersticas especficas do computador. Para que um nmero seja representado nesta
verso, devemos indicar explicitamente, como no exemplo a seguir.
> 1234567890::Int
1234567890 :: Int

> 12345678901::Int
Program error: arithmetic overflow
O exemplo a seguir ilustra a diferena entres as duas possibilidades.
> 1089979879870979879
1089979879870979879 :: Integer
> 1089979879870979879::Int
Program error: arithmetic overflow
O conjunto de operaes associadas ao domnio pode variar. Em geral so fornecidas as
seguintes operaes primitivas:
Nome Descrio Exemplos
+ Adio
> 13 + 15 + 21 + 24 + 27 + 31
131 :: nteger
* Multiplicao
> 20 * 10 * 98
19600 :: nteger
- Subtrao
> 1234 - 4321
-3087 :: nteger
36
div,quot diviso inteira
> div 12834 10
1283 :: nteger
^ Potncia
> 2^20
1048576 :: nteger
rem
resto da diviso inteira entre
dois inteiros
> rem 12834 10
4 :: nteger
> rem (12834 10)
-4 :: nteger
mod
mdulo da diviso inteira entre
dois inteiros
> mod 12834 10
4 :: nteger
> mod (-12834) 10
6 :: nteger
abs valor absoluto
> abs 123
123 :: nteger
> abs (-123)
123 :: nteger
signum
produz -1, 0 ou 1, indicando
quando o nmero negativo,
zero ou positivo
> signum (-3888876527829798)
-1 :: nteger
> signum 0
0 :: nteger
> signum 3
1 :: nteger

Algumas observaes so importantes:
a) As operaes podem ser combinadas para construir expresses mais
complexas;
> 5 + 12 * 3
41 :: nteger
b) As operaes possuem precedncia, ou seja, existe uma ordem em que
devem ser consideradas. No exemplo anterior, a multiplicao (*) tem
precedncia sobre a adio (+) e portanto realizada antes da adio. Esta
precedncia pode ser modificada pelo uso de parntesis.
> (5 + 12) * 3
51 :: nteger
c) A operao div (diviso) parcial, ou seja, no se aplica quando o
denominador nulo. Quando submetemos uma expresso com esta
caracterstica, o HUGS no avalia a expresso e sinaliza que h um erro.
> div 398 0
Program error: divide by zero
37
5.3. NMEROS REAIS
O tipo em Haskell para representao dos nmeros reais nos computadores denominado
;loat. Para este tipo no falaremos de uma lista de constantes. Ao invs disso falaremos
aqui em magnitude e preciso de um nmero. Como na notao cientfica. A preciso nos
diz quantos algarismos significativos so usados e a magnitude nos diz qual o maior
expoente admitido.
Por exemplo, uma determinada implementao pode utilizar 6 algarismos
significativos. Nesta, o nmero 123456.789 seria representado pelo nmero 123457.0,
onde o 6 foi arredondado para 7.
A magnitude permite a representao de nmeros bem pequenos e bem grandes.
Por exemplo, um nmero muito grande como 99999999999999999999999999999 poderia
ser representado por 1.0e+29 e um nmero bem pequeno como
0.00000000009999999999999999999999999999, poderia ser representado por 1.0e-010.
Veja os exemplos a seguir:
> 0.1234567890123456789012345678901234567890
0.123456789012346 :: DoubIe
A representao cientfica utilizada quando necessrio:
> 1234567890123456789012345678.9
1.23456789012346e+027 :: DoubIe
A implementao corrente do HUGS usa uma verso estendida do tipo Float, denominada
DoubIe. Se desejarmos, podemos representar os nmeros usando uma quantidade menor
de algarismos significativos, para isso precisamos explicitar que o nmero considerado
deve ser representado como do tipo FIoat.
> 0.1234567890123456789012345678901234567890::FIoat
0.1234568 :: FIoat
O nmero pi definido com uma constante do tipo Double. Se houver necessidade do uso
do valor de pi nas expresses descritas no Haskell, basta escrever a palavra pi, que ser
avaliada como a constante 3,14159... Veja o exemplo a seguir:
> pi
3.14159265358979 :: Double
O conjunto de operaes aqui tambm pode variar. Em geral, as listadas no quadro abaixo
so providas.
38
Nome Descrio ExempIos
+ Adio
> 2.5 + 3.3216 + 0.389458
6.211058 :: Double
* Multiplicao
> 3.2 * 1.23 * 0.208
0.818688 :: Double
- Subtrao
> 3.456789 - 1.344499089877
2.112289910123 :: Double
/ Diviso
> 9.345988 / 234569.34
3.98431781408431e-005 :: Double
^
potncia (o expoente tem que ser nt
e positivo)
> 1.5324^10
71.4038177956654 :: Double
sin Seno
> sin pi
1.22460635382238e-016 :: Doubl
cos Coseno
> cos pi
-1.0 :: Double
tan Tangente
> tan ( pi / 4.0)
1.0 :: Double
sqrt raiz quadrada
> sqrt 8.5
2.91547594742265 :: Double
log logaritmo na base e
> log 2.71828182845905
1.0 :: Double
logBase logaritmo na base escolhida
>logBase 10 2
0.301029995663981 :: Double
exp potncia na base e
> exp 1.0
2.71828182845905 :: Double

Da mesma forma como ocorre nos nmeros inteiros, nos reais tambm possvel
combinar operaes para construir expresses mais complexas. Tambm vale para os
reais a precedncia de operadores. Como nos inteiros podemos usar parntesis para
controlar a ordem em que as operaes sero realizadas.
5.4. CONVERSO DE TIPOS
Em Haskell os inteiros so tratados como um subconjunto dos reais. Assim, quando temos
nmeros reais misturados com nmeros inteiros em uma mesma expresso, os nmeros
inteiros so automaticamente tratados como reais.
> 3 + 5
8 :: nteger
> 3 + 5.0
8.0 :: Double
Existem funes especficas para converso de tipos:
39
a) a funo truncate converte um real x para o menor inteiro menor ou igual x.
> truncate pi
3 :: nteger
b) a funo round converte um real x para o inteiro mais prximo de x, ou seja:
round x = truncate (x + 0.5)
> round pi
3 :: nteger
> round (exp 1)
3 :: nteger
Outras exemplos de funes que existem s com o intuito de converso de tipos so
fromnteger e fromRational. As assinaturas delas so:
fromnteger :: (Num a) => nteger -> a
fromRational :: (Fractional a) => Rational -> a
5.5. PRECEDNCIA DOS OPERADORES
Quando aparecem vrios operadores juntos na mesma expresso, certas regras de
precedncia so estabelecidas para resolver possveis ambigidades. A ordem em que os
operadores so considerados a seguinte:
1) di7, mod, abs, sqrt e qualquer outra funo
2) ^
3) * /
4) +, -
Da mesma forma que na matemtica usual podemos usar os parntesis para forar
uma ordem diferente de avaliao.
ExempIos:
> 2 + 3 * 5
17
O operador * tem precedncia sobre o operador +. Podemos escrever a expresso a seguir
para denotar a seqncia de avaliaes:
40
2 + 3 * 5 2 + 15 17
> (2 + 3) * 5
25
A ordem de avaliao foi alterada pelo uso dos parntesis. A seqncia de avaliao
portanto:
(2 + 3) * 5 5 * 5 25
> 3 * mod 10 4 + 5
11
A prioridade para avaliao do operador mod, seguida da avaliao do operador * e
finalmente do operador +. Podemos escrever a seguinte seqncia de avaliao:
3 * mod 10 4 + 5 3 * 2 + 5 6 + 5 11
> 3 ^ mod 10 4
9
A primeira avaliao do operador mod e em seguida avaliado o operador ^. A
seqncia de avaliao :
3 ^ mod 10 4 3 ^ 2 9
> 4 ^ mod (div 20 4) 2
4
A seqncia de avaliao :
4 ^ mod (div 20 4) 2 4 ^ mod 5 2 4 ^ 1 1
5.6. ORDEM DE ASSOCIAO
Quando h ocorrncia de operadores de mesma precedncia leva-se em considerao a
ordem de associao que pode ser direita ou esquerda.
1. O operador de subtrao faz associao esquerda,
5 - 4 - 2 = (5 - 4) - 2 e no 5 - ( 4 - 2)
2. J o operador de exponenciao faz associao direita,
3 ^ 4 ^ 5 = 3 ^ ( 4 ^ 5 ) e no ( 3 ^ 4 ) ^5
41

O uso adequado das noes de precedncia e associao serve tambm para
escrevermos expresses com economia de parntesis.
Observaes:
a) O operador unrio - deve ser sempre representado entre parnteses quando utilizado
junto com outro operador: (- x)^y ou - (x^y) e nunca -x^y ou x^-y
b) A exponenciao, quando repetida em uma expresso, avaliada da direita para a
esquerda: 2^3^3 = 2^(3^3)
c) Os demais operadores, na situao acima, so avaliados da esquerda para a direita: 2 -
3 - 5 = (2 - 3) 5 e 2 + 3 + 3 = (2 + 3) + 3
ExempIos:
>3 - 7 - 2
- 6> 3 * 7 + 4
25
> 3 * ( 7 + 4)
33
> 3 ^ ( 1 + 3)
81
5.6. TIPOS DE NOVAS DEFINIES DE FUNES
Ao definir novas funes, o fazemos tomando por base os tipos de dados existentes na
linguagem. O corpo dessas definies tem por base a composio das operaes
fornecidas por estes tipos bsicos. Assim, o tipo do dado resultante da avaliao de uma
aplicao desta nova funo, pode ser antecipado por um analisador de tipos, antes
mesmo de avaliar a expresso.
Observe as duas definies a seguir:
mediaA x y = (x + y) / 2 e mediaB x y = truncate ((x + y) / 2)
O tipo de dado resuItante da apIicao da funo mediaA reaI, uma vez que a
operao "/" (diviso) s se apIica a nmeros reais. Da mesma forma, o tipo
resuItante da apIicao da funo mediaB inteiro, dado que a Itima operao
reaIizada (truncate), converte reais para inteiros. Confira nas avaIiaes a seguir:
> mediaA 3 4
3.5 :: Double
> mediaB 3 4
3 :: nteger
42
5.7. HIERARQUIA DE TIPOS
At agora dissemos que a linguagem Haskell trabalha com dois tipos numricos, os reais e
os inteiros. sto uma verdade irrefutvel. Ao avaliar uma expresso numrica o resultado
ser sempre um nmero real ou um nmero inteiro.
Entretanto, para viabilizar as converses automticas de tipo, a linguagem Haskell realiza
os nmeros atravs de uma hieraquia de classes. A classe numrica mais geral Num,
dela derivam as classes ReaI e FractionaI. De ReaI derivam IntegraI e ReaIFrac. De
FractionaI derivam ReaIFrac e FIoating. De ReaIFrac e de FIoating deriva ReaIFIoating.
Algumas classes derivam de mais de uma classe, ao que denominado de herana
mltipla, como o caso de ReaIFrac que deriva das classes ReaI e FractionaI. A Figura
5.1 apresenta a hierarquia completa. Podemos observar aqui trs classes de apoio, usadas
para estruturar as derivaes, Ord, Eq e Enum.
Aqui devemos entender classe como uma coleo de operadores sobre um determinado
conjunto de valores. Uma classe derivada herda todas as funes providas por sua
ancestral e pode acrescentar novas.
Figura 5.1 Hierarquia de Tipos
5.7.1 Eq
43
Eq
Ord Num
ReaI FractionaI Enum
IntegraI
ReaIFrac FIoating
ReaIFIoating
A classe Eq introduz na linguagem a possibilidade de fazer-se distino entre os valores de
um determinado tipo, sendo a classe mais bsica. Com valores que so instncias desta
classe podemos aplicar as operaes de igualdade e desigualdade. Podemos pensar
como se esta classe tivesse como membros todos os valores sobre os quais se pode fazer
distino. O tipo Bool ser apresentado em detalhes no Captulo 6.
funes assinatura descrio informaI
(==) a -> a -> Boo
l
Avalia se dois valores so idnticos
(/=) a -> a -> Boo
l
Avalia se dois valores so distintos
Observemos que a comparao sempre realizada com valores do mesmo tipo.
ExempIos:
Hugs> 3 == 3.0
True :: Bool
Hugs> 3.0 /= 3
False :: Bool
Hugs> 'a' == 'a'
True :: Bool
Hugs> 'a' == 'b'
False :: Bool
Hugs> 'a' == head "abacate"
True :: Bool
Hugs> [1,2,3]==[1..3]
True :: Bool
Hugs> [1,2,3]==['1', '2', '3']
ERROR - Cannot infer instance
*** Instance : Num Char
*** Expression : [1,2,3] == ['1','2','3']
Hugs> 3 /= 'a'
ERROR - Cannot infer instance
*** Instance : Num Char
*** Expression : 3 /= 'a'
Hugs> 3.0 == 2.999999999999999999999999999999
True :: Bool
Hugs> 2.9999999999999999999999999999999 == 2.9999999999999999
True :: Bool
Hugs> 2.9999999999999999999999999999999 == 2.999999999999999
False :: Bool
Observemos que:
a) A comparao sempre realizada com valores do mesmo tipo. Nos exemplos
acima, a tentativa de comparar valores de tipos diferentes resulta em uma
mensagem de erro, avisando que estamos tentando comparar um valor da classe
Num com um valor da classe Char;
44
b) A igualdade de nmeros dependente de uma representao interna, como
podemos observar pelos trs ltimos exemplos.

5.7.2 Ord
Esta uma classe mais geral que as dos nmeros, provendo suporte para construo de
outras classes, inclusive as classes numricas. A idia geral prover operaes para
todos os conjuntos de valores que podem ser ordenados.
funes assinatura descrio informaI
compare a -> a -> Ordering Compara dois valores associando-
os a constantes LT, EQ e GT
compare x y =
LT se x menor que y
EQ se x igual a y
GT se x maior que y
(<), (<=), (>=), (>) a -> a -> Bool Operadores relacionais que
compara dois valores resultando em
um valor booleano (True ou False)
max a -> a -> a max x y =
x se x maior ou igual a y
y em caso contrrio
min a -> a -> a min x y =
x se x menor ou igual a y
y em caso contrrio
ExempIos:
Hugs> compare 3 4
LT :: Ordering
Hugs> min 3 4
3 :: nteger
Hugs> min 4 3
3 :: nteger
Hugs> max 4 3
4 :: nteger
Hugs> max 3 4
4 :: nteger
Hugs> 3 <=4
True :: Bool
Hugs> compare 'g' 'b'
GT :: Ordering
Hugs> "abacaxi" > "abacate"
True :: Bool
Hugs> max "abacaxi" "melancia"
"melancia" :: [Char]
Hugs> min "abacaxi" "melancia"
45
"abacaxi" :: [Char]
5.7.3 Enum
Esta uma classe que introduz funes para descrever e operar com seqncia de
valores.
funes assinatura descrio informaI
succ, a -> a
pred a -> a
toEnum Int -> a
fromEnum a -> Int
enumFromThen a -> a -> [a] [n,n'..]
enumFromTo a -> a -> [a] [n..m]
enumFromThenTo a -> a -> a -> [a] [n,n'..m]
Atemos-nos aqui a comentar as funes "succ e "pred, as demais sero apresentadas
junto com listas, no capitulo que introduz este tipo de valores. A funo "succ determina o
sucessor de um valor na seqncia de valores da qual faz parte e a funo "pred
determina o seu predecessor.
ExempIos:
Hugs> succ (-5)
-4 :: Integer
Hugs> pred 0
-1 :: Integer
Hugs> succ 0
1 :: Integer
Hugs> pred (succ 0) == succ (pred 0)
True :: Bool
Hugs> pred 'a'
'`' :: Char
Hugs> pred 'b'
'a' :: Char
Hugs> succ 'B'
'C' :: Char
Hugs> succ '0'
'1' :: Char
Hugs> pred 1.0
0.0 :: Double
Hugs> succ 0.99999
1.99999 :: Double
46
5.7.4 Num
A classe Num a mais geral para os nmeros e prov as funes, (+), (-), (*), negate,
signum e abs.
funes assinatura descrio informaI
(+), (-), (*) a -> a -> a
Adio, subtrao e multiplicao usuais
negate a -> a
Define o simtrico de um nmero
abs a -> a
Define o valor absoluto de um nmero
signum a -> a
signum x =
1 se x positivo;
-1 se x negativo e
0 se x nulo
fromInteger Integer -> a
Converte um valor do tipo Integer em um
valor do tipo Num
Na prtica isto significa que qualquer nmero usado em Haskell pode ser operado por
estas funes.
ExempIos:
Hugs> 3 + 4
7 :: Integer
Hugs> 3.0 + 4.0
7.0 :: Double
Hugs> :t 3 + 4
3 + 4 :: Num a => a
Hugs> :t 3.0 + 4.0
3.0 + 4.0 :: Fractional a => a
Hugs> 3 + 4
7 :: Integer
Hugs> 3.0 + 4.0
7.0 :: Double
Hugs> negate 3
-3 :: Integer
Hugs> negate 4.0
-4.0 :: Double
Hugs> signum (-3)
-1 :: Integer
5.7.5 ReaI
A classe ReaI possui uma herana mltipla, descendendo das classes Num e Ord. sto
significa que com um valor desta classe podemos operar tanto com as operaes da
classe Num quanto com as operaes providas por Ord. A classe Real introduz a funo
toRational para converso de um valor do tipo ReaI em um valor do tipo RationaI.
funes assinatura descrio informaI
toRational a -> Rational
toRational x = p % q
onde p e q so nmeros inteiros e
x o cociente de p dividido por q
47
ExempIos:
Hugs> toRational 5.5
11 % 2 :: Ratio Integer
Hugs> toRational 1.25
5 % 4 :: Ratio Integer
Hugs> toRational 0.75
3 % 4 :: Ratio Integer
Hugs> toRational 75
75 % 1 :: Ratio Integer
Hugs> toRational 1.5
3 % 2 :: Ratio Integer
Hugs> 3%4 + 2%3
ERROR - Undefined variable "%"
A classe RationaI no est disponvel no mdulo Prelude e precisa ser importada ou
carregada da biblioteca (package/haskell98/ratio.hs). No ltimo exemplo acima a tentativa
de operar dois valores do tipo RationaI produz uma mensagem de erro, tendo em vista
que a biblioteca no havia sido carregada.
5.7.6 FractionaI
A classe FractionaI descende diretamente da classe Num e introduz a diviso, a funo
inversa e uma converso de valores do tipo Rational para Fractional.
funes assinatura descrio informaI
(/) a -> a -> a
recip a -> a
recip x = 1 / x
fromRational Rational -> a
ExempIos:
Hugs> recip 5
0.2 :: Double
Hugs> toRational 2.5
5 % 2 :: Ratio Integer
Hugs> fromRational (5 % 2)
ERROR - Undefined variable "%"
Hugs> :l "packages/haskell98/ratio.hs"
Ratio> fromRational(3 % 4)
0.75 :: Double

48
Nos trs ltimos exemplos podemos observar: a) a tentativa de usar a funo fromRational
provoca um erro tendo em vista que a biblioteca no estava disponvel; b) a carga da
biblioteca e c) o uso de fromRational.
5.7.7 IntegraI
A classe IntegraI possui uma herana mltipla, descendendo das classes ReaI e Enum.
As funes introduzidas por esta classe so apresentadas a seguir.
funes assinatura descrio informaI
quot, rem, div, mod a -> a -> a
quotRem, divMod a -> a -> (a,a)
toInteger a -> Integer
ExempIos:
Hugs> mod (-5) (3)
1 :: Integer
Hugs> rem (-5) (3)
-2 :: Integer
Hugs> divMod (-5) (3)
(-2,1) :: (Integer,Integer)
Hugs> quotRem (-5) (3)
(-1,-2) :: (Integer,Integer)
5.7.9 ReaIFrac
A classe ReaIFrac descende diretamente das classes ReaI e FractionaI introduzindo
funes
class (Real a, Fractional a) => RealFrac a where
properFraction :: (Integral b) => a -> (b,a)
truncate, round :: (Integral b) => a -> b
ceiling, floor :: (Integral b) => a -> b
5.7.10 FIoating
A classe FIoating descende diretamente da classe FractionaI introduzindo funes
importantes entre as quais as de exponenciao, de logaritmo, raiz quadrada e as
trigonomtricas.

funes assinatura descrio informaI
pi a
exp, log, sqrt a -> a
(**), logBase a -> a -> a
sin, cos, tan a -> a
asin, acos, atan a -> a
49
sinh, cosh, tanh a -> a
asinh, acosh, atanh a -> a
Ao definir novas funes, o fazemos tomando por base os tipos de dados existentes na
linguagem. O corpo dessas definies tem por base a composio das operaes
fornecidas por estes tipos bsicos.
Exerccios:
1. Qual o tipo resultante da avaliao da definio da funo mediaC x y = div (x + y) 2?
2. O que ocorre na avaliao de uma expresso em Haskell que usa a definio da funo
mediaD x y = div (x + y) 2.0 ?
50
6. EXPRESSES LGICAS E O TIPO BOOLEAN
6.1. INTRODUO
Uma caracterstica fundamental dos agentes racionais a capacidade de tomar decises
adequadas considerando as condies apresentadas pelo contexto onde est imerso. Uma
mquina que sabe apenas fazer contas, ou seja, manusear as operaes aritmticas, ter
sua utilidade fortemente reduzida e, portanto no despertar tantos interesses prticos. Os
computadores que temos hoje so passveis de serem programados para tomada de
deciso, ou seja, possvel escolher entre duas ou mais aes, aquela que se deseja
aplicar em um determinado instante. Em nosso paradigma de programao precisamos de
dois elementos fundamentais: um tipo de dados para representar a satisfao ou no de
uma condio e um mecanismo que use essas condies na escolha de uma definio.
Neste captulo discutiremos a natureza das proposies lgicas, sua aplicabilidade na
resoluo de problemas e introduziremos um novo tipo de dados, denominado booIean.
Satisfazendo logo de sada a curiosidade do leitor lembramos que o nome uma
homenagem a George Boole que estudou e formalizou as operaes com estes tipos de
valores.
6.2. PROPOSIES LGICAS
Revirando o ba das coisas estudadas no ensino fundamental, por certo encontraremos as
sentenas matemticas. Lembraremos ento que elas so afirmaes sobre elementos
matemticos, tais como os exemplos a seguir:
1. vinte e dois maior que cinco
2. dois mais trs igual a oito
3. todo nmero primo impar
O conceito de proposio lgica mais geral, aplicando-se s mais diversas situaes do
cotidiano, como nos exemplo a seguir:
1. Maria namorada de Pedro
2. Jos apaixonado por Maria
3. Hoje domingo
Analisando o significado da informao contida em uma proposio lgica, podemos
concluir que ela ser uma afirmao verdica quando se referir a fatos que realmente
acontecem em um determinado mundo. Quando isso no ocorre, conclumos que elas so
falsas. Para podermos avaliar uma dada proposio, necessrio ter acesso ao mundo
considerado.
Sentenas Fechadas: as sentenas 1 a 6 possuem uma caracterstica importante: todos
os seus componentes esto devidamente explicitados. Denominamos estas sentenas de
sentenas fechadas. Uma sentena fechada pode ser avaliada imediatamente, conferindo
o que elas afirmam com o mundo sobre o qual elas se referem.
Sentenas Abertas: so outro tipo de proposio importante. Nestas, alguns personagens
no esto devidamente explicitados e, portanto a sentena no pode ser avaliada. Quando
51
tratamos sentenas abertas, antes necessrio instanci-las para algum valor. Por
exemplo, a sentena matemtica
x + 5 ' %-
nem sempre verdadeira. Depende do valor que atribuirmos varivel x. Quando
atribumos valores s variveis de uma sentena dizemos que estamos instanciando a
sentena.
No caso acima, podemos instanciar a sentena para os valores 3 e 10, entre outros,
obtendo as seguintes instncias:
3 + 5 > 10
10 + 5 > 10
Agora podemos avali-las e concluir que a segunda verdica e a primeira no.
Sentenas Compostas: O discurso do cotidiano e at o discurso matemtico podem ser
escritos como uma lista de proposies simples. Exemplos:
1. Hoje domingo
2. Aos domingos tem futebol
3. Quando meu time joga, eu assisto
Nem sempre isto desejvel ou suficiente. Para resolver a questo, podemos contar com
as sentenas compostas. Como por exemplo:
a) Gr;s 4 menor que cinco e o quatro tamb4m9
b) Fomingo irei ao futebol ou escre7erei notas de aula9
c) >speranto no 4 uma linguagem de programao
Observamos ento, o surgimento de trs palavras para criar essas sentenas e que essas
palavras ( e, ou, n4o) no se referem a coisas, propriedades ou fenmenos de um
determinado universo. Elas so denominadas de palavras lgicas, visto que a sua funo
na linguagem possibilitar a articulao entre as proposies do discurso.
A composio de uma proposio pode envolver vrias palavras lgicas, como nos
exemplos a seguir:
1. =ois !enor que tr@s e !aior que u! !as n4o !aior que a so!a de tr@s
co! doisA
2. Maria ,osta de Bedro e de Coana !as n4o ,osta de 2ntonio#
AvaIiao de Sentenas Compostas: Para avaliar sentenas simples, vimos que bastava
inspecionar o mundo ao qual ela se refere e verificar se a situao expressa pela sentena
ocorre ou no. E como proceder para as sentenas compostas? Um caminho que parece
confivel apoiar essa avaliao no papel representado por cada uma das palavras
lgicas. Assim, ao considerarmos a proposio
Doje fui ao cine!a e ao teatro,
52
s poderemos dizer que ela verdica se tanto a proposio Doje fui ao cine!a quanto a
proposio Doje fui ao teatro forem avaliadas como verdicas.
Para a proposio composta
Maria foi E !issa ou ao cine!a1
devemos consider-la como verdica se uma das duas proposies:
%# Maria foi E !issa
2. Maria foi ao cine!a
forem avaliadas como verdica. E se as duas forem avaliadas como verdicas? No discurso
cotidiano tendemos a pensar nesta situao como inverdica visto que queramos uma ou
outra. A linguagem natural no estabelece se devemos ou no explicitar que no estamos
falando do caso em que ambas podem ser constatadas. Podemos assumir, portanto, que a
nossa sentena composta usando ou ser avaliada como verdica quando pelo menos
uma das duas proposies que a compe for avaliada com verdica.
No caso da sentena composta usando a palavra lgica n4o, como em
Doje n4o c7o$eu
diremos que ela ser avaliada como verdica quando a proposio Doje c7o$eu no puder
ser constatada e como inverdica no caso oposto.
6.3. O TIPO DE DADOS BOOLEAN
Podemos agora discutir sobre a natureza do valor resultante da avaliao de uma
sentena. A avaliao de natureza funcional, ou seja, dada uma sentena s ela ser
mapeada em um de dois valores distintos. Ento, o contradomnio de uma avaliao um
conjunto com apenas dois valores, um para associar com avaliaes verdicas e outras
com as inverdicas. Podemos escolher um nome para esses valores. Historicamente, as
linguagens de programao os tem denominado de Frue e ;alse. O primeiro para associar
com as proposies que podem ser constatadas no mundo considerado e a segunda com
as no constatveis. Para a avaliao das proposies compostas, podemos considerar
uma funo matemtica cujo domnio e contradomnio so definidos como o conjunto que
acabamos de definir com as constantes Frue e ;alse. Assim
aval :: <sentena> {True, False}
As proposies compostas podem ser formadas pelas operaes lgicas de conjuno,
disjuno ou negao. Em Haskell, essas operaes so representadas por:
Operao
Igica
Operador
Igico
(HaskeII)
e &&
ou ||
no not
53
Vamos ento formalizar a avaliao de sentenas compostas.
Sejam s1 e s2 duas proposies lgicas:
1. O valor lgico da sentena s% GG s2 Frue se e somente se o valor lgico de s%
Frue e o valor lgico de s2 Frue e ;alse em caso contrrio;
2. O valor lgico da sentena s% HH s2 ;alse se e somente se o valor lgico de s%
;alse e o valor lgico de s2 ;alse e Frue em caso contrrio:
3. O valor lgico da sentena not s% Frue se e somente se o valor lgico de s%
;alse e ;alse em caso contrrio.
TabeIa Verdade: Estas definies tambm podem ser representadas atravs de uma
enumerao de suas associaes, formando o que se costuma chamar de Fa+elas
Ierdade as quais apresentamos a seguir.
s1 s2 s1 && s2
True True True
True False False
False True False
False False False
s1 s2 s1 || s2
True True True
True False True
False True True
False False False
s1 not s1
True False
False True
6.4. OPERADORES RELACIONAIS
Quando falamos de proposies lgicas no discurso matemtico, ou melhor, em sentenas
matemticas, usamos termos tais como: "menor do que, "menor ou igual, "diferente,
entre outros. Estes termos so fundamentais para a nossa inteno de prover os
computadores com a capacidade de deciso. Denominamos estes elementos de
operadores reIacionais, pois estabelecem uma relao de comparao entre valores de
um mesmo domnio. O contradomnio deles do tipo Boolean. A tabela a seguir apresenta
esses operadores, suas representaes no Haskell, seus significados e exemplos de uso.
operador si,nificado exe!plo resultado
== igualdade (2 + 3) == (8 3) True
/= Diferena 5 /= (4 * 2 -3) False
< Menor (2 + 3) < 6 True
<= Menor ou igual (2 * 3) <= 6 True
> Maior (4 + 2) > (2 * 3) False
>= Maior ou igual (8 3 * 2) >= (15 div 3) False
Podemos usar estes operadores para construir novas definies ou simplesmente,
em uma sesso de Hugs na avaliao de uma expresso, como apresentado nos
exemplos a seguir.
54

> 5 > 4
True :: Bool
> 4 /= (5 + 3)
True :: Bool
> (mod 5 2) == (rem 5 2)
True :: Bool
> (mod (-5) 2) == (rem (-5) 2)
False :: Bool
> (div 5 2) <= truncate(5.0 / 2.0)
True :: Bool

6.5. EXPRESSES E DEFINIES
Agora que temos um novo tipo de dados, podemos utiliz-lo a nosso servio, escrevendo
expresses de forma to natural quanto aquela que usamos para escrever expresses
aritmticas. Usando essas expresses podemos ento construir definies cujo tipo
resultante seja booleano. Os ingredientes bsicos para construir essas expresses so os
operadores relacionais.
Expresses simpIes: Por exemplo, para construir uma definio que avalie se um
nmero par, podemos usar a seguinte definio:

par x = (mod x 2) == 0
Vejamos alguns exemplos de avaliao da funo par:

> par 5
False
> par 148
True
> par 0
True
> par (truncate ((5 + 2) / 2))
False
Outros exemplos de definies:
55
Verificar se a
mltiplo de +
multiplo a b = (mod a b) == 0
Verificar se a
divisor de +
divisor a b = multiplo b a
Verificar se uma
distncia d igual
diagonal de um
quadrado de lado a
diag d a = (a * sqrt 2.0) == d
Verificar se um
nmero um
quadrado perfeito
quadp n = (sqrt n)^2 == n
Verificar se dois
nmeros a e + so
termos consecutivos
de uma P.A. de
razo r
spa a b r = (a + r) == b
Expresses compostas: Podemos usar agora os operadores lgicos para construir
expresses compostas. Veja os exemplos a seguir:
Verificar se 3
nmeros esto em
ordem decrescente
ordc a b c = (a > b) && (b > c)
Verificar se um
nmero x est no
intervalo fechado
definido por a e +
pert x a b = (x >= a) && (x <= b)
ou
pert x a b = not ((x < a) || (x > b))
Verificar se um
determinado ponto
do espao
cartesiano est no
primeiro quadrante
pquad x y = (x > 0) && (y > 0)
Verificar se 3
nmeros a, + e c,
so lados de um
tringulo retngulo
tret a b c = ((a^2 + b^2) = = c^2) ||
((a^2 + c^2) = = b^2) ||
((b^2 + c^2) = =a^2)
Quando nossas expresses possuem mais de um operador lgico devemos observar
a precedncia de um sobre o outro. Por exemplo, na expresso
P || Q && R
as letras P, Q e R so expresses lgicas. O operador && ser avaliado primeiro pois tem
precedncia sobre o ||, portanto a expresso ser avaliada para True se P for avaliado
para True ou se a subexpresso (Q && R) for avaliada para True.
56
Podemos modificar esta ordem utilizando parntesis como nas expresses
aritmticas. A expresso acima poderia ser reescrita como
(P || Q) && R
Agora, para que ela seja avaliada para verdadeira preciso que R seja avaliada
como verdadeira.
Vejamos mais alguns exemplos de definio de funo booleana:

Verificar se x est
fora do intervalo
definido por a e b e a
e b esto em ordem
no decrescente
f x a b = ((x <=a) || (x >= b)) && (a <= b)
Verificar se x
menor que a ou se x
maior que b e a e
b esto em ordem
no decrescente
g x a b = (x <=a) || (x >= b) && (a <= b)
6.6. RESOLVENDO UM PROBLEMA: Desejamos verificar se um determinado ponto do
espao cartesiano est dentro ou fora de um retngulo paralelo aos eixos, conhecidos o
ponto, o canto superior esquerdo e o canto inferior direito do retngulo.
Etapa 1 [Entendendo o problema] O ponto pode estar em qualquer quadrante? E o
retngulo, pode estar em qualquer quadrante? Basta ter os dois cantos para definir o
retngulo? Em que ordem sero informados os cantos? Como se descreve um canto? Um
ponto que esteja sobre um dos lados, est dentro ou fora do retngulo?
Vamos assumir ento as seguintes decises: discutiremos inicialmente apenas sobre
pontos e retngulos localizados no primeiro quadrante. A ordem em que os dados sero
informados ser: primeiro o ponto, depois o canto superior esquerdo e por ltimo o canto
inferior direito. Para cada ponto sero informadas as duas coordenadas, primeiro a
abscissa e depois a ordenada. Os pontos na borda so considerados pertencentes ao
retngulo.
Etapa 2 [Planejando a Soluo]: Conheo algum problema parecido? Posso
decompor este problema em problemas mais simples? Sei resolver um problema mais
geral em que este um caso particular?
Bom, j nos envolvemos com o problema para verificar se um ponto estava num
intervalo linear, este tambm se refere a intervalo. Verificar se um ponto pertence a uma
regio qualquer do espao n-dimensional mais geral, se eu conhecesse uma definio
para este problema geral, bastaria instanci-la. Ser que posso decompor o problema na
verificao de dois espaos lineares, um definido pelos lados paralelos ao eixo das
ordenadas e outro paralelo ao eixo das abscissas? Se afirmativo, como combino as duas
solues?
Para que um ponto esteja dentro do retngulo necessrio que sua ordenada esteja
entre as ordenadas dos dois cantos. Sabemos tambm que a abscissa precisa estar entre
57
as abscissas dos dois cantos. sso basta? Para combinar as solues percebemos que
suficiente que as duas primeiras estejam satisfeitas.
Etapa 3 [Construindo a Soluo] Construindo a soluo - Anteriormente j
elaboramos a definio de pertinncia a um intervalo linear, vamos us-la aqui.
pert x a b = (x>=a) && (x <= b) pertinncia linear
pertsup x y x1 y1 x2 y2 = (pert x x1 x2) && (pert y y2 y1) pertinncia no plano
E o teste, para que valores interessam testar?
Etapa 4 [Analisando a Soluo]: Existem outras maneiras de resolver o problema?
Esta soluo se aplica as outras dimenses?
Exerccios
1. Avalie as expresses abaixo, explicando como foram reduzidas para o valor final, que
booleano. Se houver erro de avaliao, identifique a causa do erro.
a) 3 < 4 || 5 == 7
b) not 3 < 7
c) 3+4 <= 8 && 10 /= 34.7
d) not (3 == 3) || not (4 /= 5) || 7 < 15 && 7 > 2
2. Dado um ponto P(x,y) do plano cartesiano, defina funes que descrevam a sua
pertinncia nas regies cinzas das figuras abaixo:
i) A regio R1 (regio cinza), do retngulo dado pelas coordenadas do canto
superior esquerdo e do canto inferior direito, como mostrado na figura abaixo:
ii) A regio R2 do losango (regio cinza), sendo dados os pontos E e D do
retngulo e sabendo-se que o crculo tangente aos lados do losango.
58
7. DEFINIES CONDICIONAIS
7.1. INTRODUO
Sabemos de nosso conhecimento matemtico que algumas funes no so contnuas
em um domnio e que, portanto, possuem vrias definies.
Em muitos casos, o domnio D de uma funo est dividido em regies disjuntas
que se complementam e, para cada uma dessas regies, existe uma expresso que define
o seu mapeamento no contra-domnio. Podemos representar esta situao pela figura
abaixo:

ExempIo 1 - Considere a funo que determina o valor da passagem area de um
adulto, para um determinado trecho, por exemplo, Vitria-Manaus, considerando a sua
idade. Pessoas com idade a partir de 60 anos possuem um desconto de 40% do valor.
Considere ainda que a passagem para o trecho considerado custe R$ 600,00.
Temos aqui duas formas de calcular o valor da passagem de uma pessoa, dividindo
o domnio em dois subconjuntos. O subconjunto dos adultos com menos de 60 anos e o
subconjunto dos demais.
Podemos definir as duas funes a seguir:
vpass1 = 600
vpass2 = vpass1 * 0.6
Para usar uma das definies, temos que explicitamente escolher a que se aplica ao
nosso caso.
ExempIo 2 - Considere a funo que associa com um determinado rendimento o
mposto de Renda a ser pago. At um determinado valor, o contribuinte no paga imposto,
e a partir de ento o rendimento dividido em faixas (intervalos), aos quais se aplicam
diferentes taxas. Suponha a tabela hipottica abaixo.

59
Faixa aIquota Desconto
inferior ou igual a 10.800 0 0
entre 10.801 e 20.000 10 1000
entre 20.001 e 30.000 20 1500
acima de 30.000 25 1800
Para descrever as vrias definies e os correspondentes subdomnios,
poderamos escrever separadamente cada definio, construindo, portanto vrias funes,
e deixar que o usurio escolha qual usar. Claro que isto traria muitos inconvenientes pois
estaramos deixando uma escolha mecnica na mo do usurio, que alm de
sobrecarreg-lo com tarefas desnecessrias, ainda estaria expondo-o ao erro por
desateno. Mas vamos l construir as funes independentes.
ir1 s = 0
ir2 s = s * 0.1 - 1000
ir3 s = s * 0.2 - 1500
ir4 s = s * 0.25 - 1800
Agora, para us-las, o usurio pega o seu salrio, olha a tabela e seleciona qual
funo aplicar.
A escolha de qual definio usar para uma dada situao em si, um tipo de
computao. Podemos descrever essa computao com expresses condicionais, vamos
deixar que o computador escolha. Descrevemos cada subdomnio com a respectiva funo
aplicvel e deixemos que ele escolha a definio a aplicar, dependendo do valor fornecido.
Vejamos ento como isso pode ser feito nas sees subseqentes.
7.2. A ESTRUTURA IF-THEN-ELSE
Uma expresso condicional construda com if*t7en*else possui a seguinte sintaxe:
if <expresso lgica> then <expresso 1> eIse <expresso 2>
onde:

<expresso lgica>
Uma expresso descrevendo uma condio a ser
satisfeita, envolvendo operadores relacionais e
operadores lgicos.
60
<expresso1> e
<expresso2>
1. Expresses descrevendo um valor a ser produzido
como resposta entrada fornecida e, como a
expresso total tem que ser de um nico tipo, as
duas expresses devem ser do mesmo tipo.
2. Cada uma destas expresses pode ser inclusive
outra condicional, dentro da qual pode haver
outras e assim sucessivamente.
3. Quando a <expresso lgica> avaliada para
Frue o valor resultante ser o que for obtido pela
avaliao da <expresso 1> caso contrrio ser o
obtido pela avaliao da <expresso 2>

Para a funo que calcula o valor da passagem area podemos ento construir a seguinte
definio:
vpass x = if x < 60 then 600 else 360
rvore de deciso: Podemos representar as expresses condicionais atravs de uma
notao grfica denominada de rvore de deciso. importante considerar que este tipo
de representao uma ferramenta importantssima para estruturarmos a soluo de
problemas que requerem expresses condicionais.

ExempIo 3 Definir a funo que determina o valor absoluto de um nmero.
Sabemos que esta funo se define em dois subdomnios:
subdomnio expresso
x < 0 - x
x >= 0 x
Como s temos duas possibilidades, podemos codificar da seguinte maneira:
absoluto x = if x < 0 then -x eIse x
61
Para concluir esta apresentao voltemos ao nosso exemplo 2 que define a funo
para clculo do mposto de Renda. O domnio neste caso deve ser quebrado em quatro
subdomnios e para cada um deles construiremos uma expresso.
domnio funo
s > 10800 ir1 s
pert s 10801 20000 ir2 s
pert s 20001 30000 ir3 s
s > 30000 ir4 s
Para a dodificao, precisaremos quebrar sucessivamente o domnio da funo em
intervalos. A determinao dos intervalos realizada da seguinte maneira: primeiro
dividimos o domnio entre o primeiro intervalo e o restante, que por sua vez, dividido
entre o segundo intervalo e o seu restante e assim sucessivamente.
A codificao final pode ser:
ir s = if s <= 10800
then ir1
else if pert s 10800 20000
then ir2
else if pert s 20001 30000
then ir3
else ir4
here
ir1 = 0
ir2 = s * 0.1 - 1000
ir3 = s * 0.2 - 1500
ir4 = s * 0.25 - 1800
pert x a b = x>=a && x<=b
7.2.1 USANDO O IF-THEN-ELSE
EXEMPLO 1: Considere um mapeamento de valores numricos onde o domnio se divide
em 4 regies, cada uma das quais possui diferentes formas de mapeamento. As regies
so apresentadas na figura abaixo, numeradas da esquerda para direita. Observe ainda
que as extremidades so abertas. Considere ainda a seguinte tabela de associaes:

regio mapeamento desejado
regio 1 o dobro de x
62
regio 2 o sucessor de x
regio 3 o quadrado de x
regio 4 o simtrico do quadrado de x
Podemos analisar as regies atravs do seguinte diagrama:
O que nos levar seguinte definio:
f x = if x < 0
then if x < (-15)
then 2 * x
else x + 1
else if x < 10
then x ^2
else - (x ^ 2)
Exemplo 2: Dados trs nmeros inteiros distintos, determinar o maior deles.
Podemos explorar uma soluo da seguinte maneira. Considere um retngulo e
divida-o horizontalmente em 2 partes, a parte de cima representa as situaes onde a > b
e a de baixo aquelas onde b > a. Divida agora o retngulo verticalmente, em cada uma das
regies anteriores surgiro 2 metades. Na de cima, representamos agora a relao entre a
e c. Na de baixo, a relao entre b e c.
x < 0
X < -15
X > 10
True
True
True
FaIse
FaIse
FaIse
63
Explorando as relaes entre os
nmeros
Representando as relaes atravs de
uma rvore de deciso
Traduzindo a rvore de deciso para Hugs, chegamos seguinte definio:
maior a b c = if a > b
then if a > c
then a
else c
else if b > c
then b
else c
7.3 DEFINIES PROTEGIDAS (guarded commands): A estrutura IF-THEN-ELSE foi
apresentada por primeiro por questes histricas, por tratar-se de uma forma pioneira de
escrever definies condicionais. Entretanto, algumas vezes podemos lanar mo de
estruturas mais simples e mais legveis.
As definies protegidas, tambm conhecidas por "guarded commands permitem que se
escreva para uma mesma funo, vrias definies, cada uma delas protegida por uma
expresso lgica.
<nome da funo> <parmetros> | <proteo 1> = <definio 1>
| <proteo 2> = <definio 2>
| <proteo 3> = <definio 3>
. . .
| <proteo n> = <definio n>
[ | otherwise = <definio n + 1> ]
A ltima clausula da definio opcional, por este motivo est apresentada dentro de
colchetes.
Vejamos como podemos reescrever a definio da nossa funo "ir para clculo do
imposto de renda.
64
ir' s | s<=10800 = ir1
| pert s 10800 20000 = ir2
| pert s 20001 30000 = ir3
|otherwise = ir4
where
ir1 = 0
ir2 = s * 0.1 - 1000
ir3 = s * 0.2 - 1500
ir4 = s * 0.25 - 1800
Exerccios
1. Reescreva, usando definies protegidas. A definio da funo que determina o
maior de 3 nmeros inteiros fornecidos.
2. Sejam C(x
1
,y
1
) o centro da circunferncia de raio r e tambm do quadrado de lados
paralelos aos eixos cartesianos e inscrito na circunferncia. Escreva uma funo
que descreva a regio de pertinncia do ponto P na figura abaixo, dados C(x
1
,y
1
) ,
r e o ponto P (x,y),
65
7
1
1
2
2
3
4
5
6
8. O TESTE DE PROGRAMAS
8.1. INTRODUO: No basta desenvolver um programa para resolver um dado
problema. preciso garantir que a soluo esteja correta. Muitos erros podem ocorrer
durante o desenvolvimento de um programa e, portanto temos que garantir que o
programa que ir ser executado est livre de todos eles. Ao conceber a soluo podemos
nos equivocar e escolher caminhos errados. Precisamos eliminar esses equvocos. Ao
codificarmos a nossa soluo podemos cometer outros erros ao no traduzirmos
corretamente nossa inteno. Esses erros podem ocorrer por um mau entendimento dos
elementos da linguagem ou at mesmo por descuido, o certo que eles ocorrem. Uma
estratgia muito til, mas no infalvel, o teste de programa.
Em sua essncia, o teste de programa consiste em submeter um programa ao
exerccio de algumas instncias do problema e comparar os resultados esperados com os
resultados obtidos.
8.2. O PROCESSO DE TESTE: Em primeiro lugar devemos escolher as instncias
apropriadas, no basta escolh-las aleatoriamente. A seguir devemos determinar, sem o
uso do programa, qual o valor que deveria resultar quando o programa for alimentado com
essas instncias. O passo seguinte consiste em submeter cada instncia ao programa e
anotar o resultado produzido por ele. Finalmente devemos comparar cada valor esperado
com o valor produzido e descrever qual o tipo de ocorrncia.
Um exempIo: Considere o problema de identificar se um dado ponto est ou no
localizado no primeiro quadrante do espao cartesiano. Considere ainda a
seguinte definio:

primquad x y = (x >= 0) && (y >= 0)
Precisamos agora verificar se ela atende nossa inteno. Para tanto devemos
escolher algumas instncias, prever o resultado esperado e em seguida submeter ao
HUGS, para ver o que acontece.
Que pares de valores deveremos escolher? Bom, vamos escolher uns pares usando
a seguinte estratgia: um par onde x maior que y, outro onde y seja maior que x e um
terceiro em que os dois sejam iguais. Gerando uma planilha como apresentada a seguir.

x y
resuItado
esperado
resuItado
obtido
diagnstico
-5 -2 False
-2 -5 False
5 5 True
Podemos agora submeter as instncias avaliao do sistema, obtendo a seguinte
interao:
66
? primquad (-5) (-2)
FaIse
? primquad (-2) (-5)
FaIse
? primquad 5 5
True
?
Podemos agora completar o preenchimento de nossa planilha, obtendo a tabela a seguir:

x y
resuItado
esperado
resuItado
obtido
diagnstico
-5 -2 False False sucesso
-2 -5 False False sucesso
5 5 True True sucesso
Verificando as diversas linhas da coluna "Diagnstico, parece que nosso programa
est correto. Veja que ele passou com sucesso em todos os testes!
Que pena que no seja verdade. Apesar de passar em todos os testes a que foi
submetido, ele no funciona corretamente. Tudo que podemos afirmar neste instante que
para os valores usados, o programa funciona corretamente. E para os outros valores, ser
que funciona corretamente?
Outros valores? Quais?
8.3. PLANO DE TESTE: Para escolher os valores que usaremos, antes de mais nada
devemos identificar as classes de valores que sero relevantes para o teste, em um
segundo instante podemos ento escolher os representantes destas classes. Quando
temos um parmetro, os possveis valores a serem usados so todas as constantes do
domnio. Para o caso de um parmetro do tipo int, existem 65536 valores diferentes.
Testar nosso programa para todos esses valores implicaria em determinar a mesma
quantidade de resultados esperados e em seguida digitar e submeter esta mesma
quantidade de instncias do problema para o sistema e ainda depois conferir um a um os
resultado obtidos com os esperados. Enfim, um trabalho imenso. magine agora se fossem
dois parmetros? A quantidade de pares seria da ordem de 4.29497 x 10^09 (algo da
ordem de quatro bilhes). E para 3 parmetros? E para n parmetros? Nmeros cada vez
mais enormes. Por este caminho, testar programas seria invivel.
Felizmente no precisamos de todos eles, basta identificar as classes distintas que
importam para o problema, ou seja, as classes de equivalncia relevantes. sto pode ser
obtido analisando o enunciado estendido do problema.
No caso de nosso exemplo anterior, analisando melhor a definio, podemos
identificar que por definio, o espao cartesiano se divide em quatro regies. A primeira,
onde ambos as coordenadas so positivas, denominamos de primeiro quadrante. A
segunda, onde a coordenada x negativa e a y positiva, denominamos de segundo
quadrante. O terceiro quadrante corresponde ao espao onde ambas as coordenadas so
67
negativas. Ainda temos o quarto quadrante onde a coordenada x positiva e a y
negativa. E os pontos que ficam em um dos eixos ou na interseo destes, qual a
classificao que eles tm? Bom, podemos convencionar que no esto em nenhum dos 4
quadrantes descritos. Resumindo, nosso plano de teste deve contemplar estas situaes,
conforme ilustrado na tabela a seguir.
x y quadrante
positivo positivo primeiro
negativo positivo segundo
negativo negativo terceiro
negativo positivo quarto
nulo
qualquer
no nulo
eixo das ordenadas
qualquer
no nulo
nulo eixo das abscessos
nulo nulo origem

bom observar ainda que este plano pode e deve ser preparado antes mesmo de
elaborar o programa, para faz-lo, precisamos apenas da especificao detalhada. Alm
disso, este plano no precisa ser feito pelo programador responsvel pela elaborao da
soluo, qualquer outro programador, de posse do enunciado detalhado, pode se
encarregar da tarefa. Este tipo de plano serve para alimentar o teste denominado de caixa
preta. Esta denominao se deve ao fato de no ser necessrio conhecermos a estrutura
da soluo para elaborar o plano. Outro aspecto positivo da elaborao do plano o mais
cedo possvel que contribu para um melhor entendimento do problema.
Voltando ao nosso exemplo, podemos agora elaborar a nossa planilha de teste
considerando as classes de equivalncia a serem definidas. Uma questo que surge
como escolhemos o representante de uma classe? Existem melhores e piores? No nosso
caso, como pode ser qualquer valor positivo ou negativo, podemos escolher valores de um
dgito apenas, no mnimo escreveremos e digitaremos menos.
x y
resuItado
esperado
resuItado
obtido
diagnstico
2 3 True
-2 3 False
-2 -3 False
2 -3 False
0 3 False
0 -3 False
2 0 False
-2 0 False
0 0 False
68
8.4. REALIZANDO O TESTE: Vejamos agora o resultado de nossa interao com o
HUGS.
? primquad 2 3
True
? primquad (-2) 3
FaIse
? primquad (-2) (-3)
FaIse
? primquad 2 (-3)
FaIse
primquad 0 (-3)
FaIse
? primquad 0 3
True
? primquad 0 (-3)
FaIse
? primquad 2 0
True
? primquad (-2) 0
FaIse
? primquad 0 0
True
?

Voltemos agora para nossa planilha e vamos preench-la na coluna de resultado obtido e
diagnstico.
x y
resuItado
esperado
resuItado
obtido
diagnstico
2 3 True True sucesso
-2 3 False False sucesso
-2 -3 False False sucesso
2 -3 False False sucesso
0 3 False True falha
0 -3 False False sucesso
2 0 False True falha
-2 0 False False sucesso
0 0 False True falha
8.5. Depurao: Uma vez testado o programa e identificado que ocorreram instncias para
as quais a nossa definio no est fazendo a associao correta, ou seja, o valor obtido
diferente do esperado, devemos passar a uma nova fase. Depurar um programa um
processo que consiste em buscar uma explicao para os motivos da falha e
posteriormente corrigi-la. Obviamente isto tambm no um processo determinante e nem
possumos uma frmula mgica. Ao longo de nossa formao de programadores iremos
69
aos poucos incorporando heursticas que facilitem esta tarefa. Por enquanto muito cedo
para falarmos mais do assunto e vamos concluir com um fechamento do problema anterior.
Aps concluir as modificaes devemos testar o programa novamente.
Depurando nossa soIuo - Podemos concluir por simples inspeo da nossa
ltima planilha (aquela com todas as colunas preenchidas) que nossa soluo est
incorreta. Uma interpretao dos resultados nos leva hiptese de que a nossa soluo
considera que quando o ponto se localiza na origem ou em um dos eixos positivos, a
nossa definio est considerando que eles esto no primeiro quadrante.
Passo seguinte, verificar se de fato nossa definio incorre neste erro. Em caso
afirmativo, corrigi-la e a seguir, resubmet-la aos testes.
Observando a nossa definio inicial, podemos concluir que de fato nossa hiptese
se confirma.
primquad x y = (x >= 0) && (y >= 0)

Podemos ento modific-la para obter uma nova definio, que esperamos que
esteja correta.
primquad x y = (x > 0) && (y > 0)

Agora submet-la novamente ao teste e ver o que acontece!
8.6. UMA SNTESE DO PROCESSO: O processo , como vimos, repetitivo e s se
encerra quando no identificarmos mais erros. O diagrama ilustra o processo como um
todo.
Bas lembre-se1 isto ainda no garante que seu programa
este@a 1!!H corretoI 2uando no identificamos erro1 apenas
podemos concluir que para as instJncias que usamos o nosso
programa apresenta os resultados esperados

70
Exerccios:
1. Dado um ponto P(x,y) do plano cartesiano, defina funes que descrevam a sua
pertinncia na regio cinza da figura abaixo (a regio R1 - regio cinza - do retngulo
dado pelas coordenadas do canto superior esquerdo e do canto inferior direito. Faa o
plano de teste para o seu programa:
71
E
D
9. RESOLVENDO PROBLEMAS - OS MOVIMENTOS DO CAVALO
9.1. INTRODUO: Considere o jogo de xadrez, onde peas so movimentadas em um
tabuleiro dividido em 8 linhas e oito colunas. Considere ainda os movimentos do cavalo, a
partir de uma dada posio, conforme diagrama a seguir, onde cada possvel movimento
designado por !i. No esquema, o cavalo localizado na posio (5, 4) pode fazer oito
movimentos, onde o primeiro deles, !%, levaria o cavalo para a posio (7,5).
8 m3 m3 m3 m3 m3 m3 m3 M3
7
6 m3 m2
5 m4 m1
4 C
3 m5 m8
2 m6 m7
1
1 2 3 4 5 6 7 8
9.2. PROBLEMA 1: Escreva uma funo que determina se, a partir de uma dada posio,
o cavalo pode ou no realizar o primeiro movimento. Vamos cham-la de p!o$, e
denominar seus parmetros (a posio corrente), de x e . Eis alguns exemplos de uso de
nossa funo e os valores esperados:
instncia resuItado
pmov 5 4 True
pmov 8 1 False
pmov 1 1 True
pmov 1 8 False
9.2.1. Soluo - A soluo pode ser encontrada atravs da construo de uma
expresso booleana que avalie se a nova posio, ou seja, aquela em que o cavalo seria
posicionado pelo primeiro movimento, est dentro do tabuleiro. Como o cavalo, no primeiro
movimento, anda duas casas para direita e uma para cima, basta verificar se as
coordenadas da nova posio no ultrapassam a oitava fileira (linha ou coluna).
Codificando em HUGS, temos ento:
pmov x y = (x + 2 <= 8 ) && (y + 1 <= 8)

9.2.2. TESTANDO A SOLUO - Como j discutimos anteriormente, para verificar
a correo de nossa soluo, devemos submet-la a um teste. Para tanto devemos
escolher as classes de equivalncias relevantes e, a partir delas, produzir a nossa planilha
de teste. Olhando para a especificao do problema, podemos identificar 4 conjuntos de
72
valores que se equivalem para os fins do nosso programa, como podemos observar na
figura abaixo:
8
7
6
5
4
3
2
1
1 2 3 4 5 6 7 8
9.2.3. Estendendo o Problema - Podemos fazer o mesmo para todos os demais
movimentos, obtendo com isso as seguintes definies:
pmov x y = (x + 2 <= 8 ) && (y + 1 <= 8)
smov x y = (x + 1 <= 8 ) && (y + 2 <= 8)
tmov x y = (x - 1 >= 1 ) && (y + 2 <= 8)
qmov x y = (x - 2 >= 1 ) && (y + 1 <= 8)
qtmov x y = (x - 2 >=1 ) && (y - 1 >= 1)
sxmov x y = (x - 1 >= 1 ) && (y - 2 >= 1)
stmov x y = (x + 1 <= 8 ) && (y - 2 >= 1)
omov x y = (x + 2 <= 8 ) && (y - 1 >= 1)
9.2.4. dentificando Abstraes - Podemos agora indagar, olhando para as oito
definies, sobre a ocorrncia de algum conceito geral que permeie todas elas.
Poderamos tambm ter feito isso antes. Como no o fizemos, faamo-lo agora. Podemos
observar que todas elas avaliam duas expresses e que ambas testam fronteiras que
podem ser margem direita, margem esquerda, margem superior ou margem inferior.
Podemos observar ainda, que o par margem direita e margem superior testam o mesmo
valor 8, assim como ocorre com as duas outras, que testam o valor 1. Com isso podemos
definir duas novas funes, f e ,, para testar estes limites. Agora, as nossas definies
anteriores podem ser reescritas, usando as duas abstraes identificadas.
pmov x y = f (x + 2 ) && f( y + 1)
smov x y = f (x + 1) && f (y + 2)
tmov x y = g (x - 1) && f (y + 2)
qmov x y = g (x - 2) && f (y + 1)
qtmov x y = g (x - 2) && g (y 1)
sxmov x y = g (x - 1) && g (y 2)
stmov x y = f (x + 1 ) && g (y 2)
omov x y = f (x + 2) && g (y 1)
f w = w <= 8
g w = w >= 1
73
9.2.5. Anlise da Soluo - O que ser que ganhamos com esta nova forma de
descrever a nossa soluo? Podemos indicar pelo menos trs indcios de vantagem na
nova soluo:
1. Clareza - Na medida em que agora est explicitado, que todas as oito funes para
verificar os movimentos possuem estrutura semelhante e que todas esto usando
funes para verificar a ultrapassagem das bordas;
2. Manuteno - Se nosso tabuleiro mudasse, ou seja, passasse a ter 9 linhas por
nove colunas, bastaria alterar a funo f e tudo estaria modificado, ao invs de
termos que alterar as oito definies.
3. Reuso - As duas funes que testam as bordas poderiam ser usadas para construir
funes para avaliar o movimento de outras peas do jogo de xadrez.
9.3. PROBLEMA 2: Sabemos que para cada posio alguns movimentos podem ser
realizados e outros no. Como ordenamos os movimentos no sentido anti-horrio,
gostaramos de obter, para uma dada posio, dos movimentos que podem ser realizados,
aquele que possui o menor ndice. Vejamos o esquema abaixo.

8 m4 m1 m3 m3 C1
7 C3 m5
6 m5 m8 m6
5 m6 m7
4
3 m2 m3
2 m1 m4
1 C4 C2
1 2 3 4 5 6 7 8
Podemos observar que o cavalo C1 s pode fazer os movimentos m5 e m6 e que o
de menor ndice m5. J o cavalo C2 s pode fazer os movimentos m3 e m4 e que o de
menor ndice o m3. Enquanto isso o cavalo C3 pode fazer os movimentos m1, m4, m5,
m6, m7 e m8. Para este caso o movimento de menor ndice o m1.
Vamos chamar esta funo de qual!o$ e, como no problema anterior, os
parmetros sero as coordenadas da posio atual do cavalo. Eis alguns exemplos de uso
de nossa funo:
nstncia resultado
qualmov 8 1 3
qualmov 8 8 5
qualmov 3 7 1
qualmov 1 1 1
74
9.3.1. SOLUO - Bem, como j sabemos, para verificar se um dado movimento !i
possvel, basta arranjar um meio de sair verificando um-a-um os movimentos, a partir do
primeiro (m1) e encontrar o primeiro que pode ser realizado. Quando isso ocorrer podemos
fornecer como resposta o seu ndice. Podemos construir para isso uma rvore de deciso.
Na raiz da rvore estar a pergunta
J poss5$el reali1ar o !o$i!ento !%JK
Em caso afirmativo (brao esquerdo da rvore), mapeamos no valor 1 e em caso
negativo (brao direito), o que devemos fazer? Bom, a podemos comear uma nova
rvore (na verdade uma sub-rvore), cuja raiz ser:
J poss5$el reali1ar o !o$i!ento !2JK
E da, prosseguimos at que todos os movimentos tenham sido considerados.
A rvore resultante ser:
9.3.2. CODFCANDO A SOLUO - Vamos ento explorar os recursos da
linguagem para transformar nosso plano em um programa que de fato possa ser
"entendido" pelo nosso sistema de programao (HUGS). Como podemos observar temos
aqui o caso de uma funo que no contnua para o domnio do problema. Pelo que
sabemos at ento, no d para expressar a soluo como uma nica expresso simples.
Resta-nos o recurso das expresses condicionais. Para verificar se um dado movimento
satisfeito podemos usar as funes que construmos anteriormente e com isso obtemos a
seguinte definio:
75
qualmov x y = if pmov x y then 1
eIse if smov x y then 2
eIse if tmov x y then 3
eIse if qmov x y then 4
eIse if qtmov x y then 5
eIse if sxmov x y then 6
eIse if stmov x y then 7
eIse if omov x y then 8
eIse 0
9.3.3. Anlise da Soluo - EM PRMERO LUGAR, NCLUMOS A RESPOSTA
GUAL A ZERO (0) QUANDO O MOVMENTO M8, O LTMO A SER AVALADO,
RESULTA EM FRACASSO. PARA QUE SERVE SSO? ACONTECE QUE SE A POSO
DE ENTRADA NO FOR VLDA, OU SEJA, UMA OU AMBAS AS COORDENADAS NO
PERTENCEREM AO NTERVALO [1, 8], NENHUM MOVMENTO SERA VLDO E SE
NO PROVDENCARMOS UMA RESPOSTA ALTERNATVA, NOSSA FUNO SERA
PARCAL. MAS STO RESOLVE DE FATO NOSSO PROBLEMA? O QUE OCORRERA
SE A POSO DE ENTRADA FOSSE (0, 0)? BOM, NOSSA FUNO DETERMNARA
QUE O PRMERO MOVMENTO PODERA SER REALZADO E STO NO VERDADE.
A NVENO DE UM RESULTADO EXTRA PARA NDCAR QUE NO H SOLUO
POSSVEL, TRANSFORMANDO UMA FUNO PARCAL EM UMA FUNO TOTAL,
PARECE SER BOA, MAS COMO FO FETA NO RESOLVEU. EM GERAL O MELHOR
NESTAS STUAES PRECEDER TODA E QUALQUER TENTATVA DE
DETERMNAR A SOLUO ADEQUADA, POR UMA AVALAO DA VALDADE DOS
DADOS DE ENTRADA. NESTE CASO, BASTARA VERFCAR SE OS DOS ESTO NO
NTERVALO [1, 8]. VAMOS CONSTRUR AQU UMA FUNO QUE AVALA A
PERTNNCA DE UM VALOR A UM NTERVALO NUMRCO, CONFORME DEFNO
A SEGUR:
pert x a b = (x >= a) && (x<=b)
Especulando um pouco mais sobre a nossa soluo, podemos observar que o
movimento !L, jamais ocorrer! Analisando os possveis movimentos chegaremos
concluso de que para nenhuma posio, o oitavo o nico movimento possvel.
Sugerimos fortemente que o leitor prove este teorema. Portanto a soluo final pode ser:
qualmov x y = if not (pert x 1 8)
|| not (pert y 1 8) then 0
eIse if pmov x y then 1
eIse if smov x y then 2
eIse if tmov x y then 3
eIse if qmov x y then 4
eIse if qtmov x y then 5
eIse if sxmov x y then 6
eIse 7
76
9.4. REVISITANDO O PROBLEMA 1: Observando a soluo encontrada para o problema
1, constatamos que embora a noo de movimento do cavalo seja nica, quem precisar
saber se um dado movimento vlido, precisar conhecer o nome das oito funes.
Embora seja cedo para falarmos de interface homem-mquina, j d para dizer que
estamos sobrecarregando nosso usurio ao darmos oito nomes para coisas to parecidas.
Ser que temos como construir uma s funo para tratar o problema? Vamos reproduzir
aqui a interface das oito:
pmov x y
smov x y
tmov x y
qmov x y
qtmov x y
sxmov x y
stmov x y
omov x y

Propositadamente escrevemos o nome delas com um pedao em vermelho e outro
em preto. Seria alguma homenagem algum time que tem essas cores? Na verdade
estamos interessados em destacar que a pequena diferena nos nomes sugere que temos
uma mesma funo e que existe um parmetro oculto. Que tal explicit-lo? Podemos agora
ter uma funo com 3 parmetros, sendo o primeiro deles para indicar o nmero do
movimento que nos interessa. A interface agora seria:
mov m x y
Agora, por exemplo, para solicitar a avaliao do stimo movimento para um cavalo em (3,
4), escrevemos:
? mov 7 3 4
True
?
Muito bem, e como codificaremos isso?
9.4.1. SOLUO - Precisamos encampar em nossa soluo o fato de que a nossa
funo possui diferentes formas de avaliao, para diferentes valores do domnio, algo
parecido com a soluo do problema 2, ou seja, a nossa funo no continua e portanto
temos que selecionar qual a definio apropriada para um determinado valor de m.
Devemos construir uma rvore de deciso. Aqui deixamos esta tarefa a cargo do leitor e
passamos direto codificao conforme apresentamos a seguir:
77
mov m x y = if not (pert m 1 8) ||
not (pert x 1 8) ||
not (pert y 1 8) then
False
else if m == 1 then pmov
else if m == ! then smov
else if m == 3 then tmov
else if m == 4 then qmov
else if m == " then qtmov
else if m == 6 then sxmov
else if m == # then stmov
else omov
here

pmov = ...
smov = ...
tmov = ...
...
9.4.2. Anlise da soluo - Ao contrrio da soluo do problema 2, onde
necessariamente a validade dos movimentos tinha que ser verificada do primeiro para o
ltimo, pois nos interessava saber qual o primeiro possvel de ser realizado, o leitor pode
observar que esta ordem aqui no necessria. Tanto faz se perguntamos primeiro se
m=7 ou se m=3. Ser que podemos tirar algum proveito disso? Alertamos o iniciante, que
devemos sempre identificar propriedades internas do problema e explor-las
adequadamente. Qual a influncia desta ordem na eficincia da avaliao de uma
expresso submetida ao HUGS? Para responder, basta lembrar que as condies so
avaliadas seqencialmente. Por exemplo, se m=8, teremos que avaliar 8 condies, se
m=1 faremos 2 avaliaes e se m est fora do domnio faremos uma avaliao. Ou seja,
no pior caso faremos 8 avaliaes e no melhor caso uma (1). Em mdia, ao longo do uso
da funo, assumindo uma distribuio uniforme dos valores de m, faremos 4 avaliaes.
E se o intervalo fosse de 100 elementos distintos, quantas avaliaes de condies
faramos em mdia? Ser possvel elaborar solues onde este nmero de avaliaes seja
menor?
9.4.3. A resposta sim! J que a ordem das avaliaes no importa, podemos
buscar uma ordem mais conveniente para reduzir o nmero de avaliaes por cada
instncia avaliada.
A idia geral para estes casos obtida a partir de um conceito de vasta utilidade na
Computao. Falamos de r$ore +inria e o leitor por certo ouvir falar muito dela ao
longo da vida enquanto profissional da rea.
O caminho consiste em dividir o intervalo considerado ao meio e fazer a primeira
pergunta, por exemplo, m<=4? Dividindo em 2 o intervalo de comparaes, para cada um
destes podemos novamente dividir ao meio, at que no mais tenhamos o que dividir,
como ilustramos no diagrama a seguir, onde cada linha representa um passo da diviso
dos intervalos.
<1 1 2 3 4 5 6 7 8 >8
78
<1 1 2 3 4 5 6 7 8 >8
<1 1 2 3 4 5 6 7 8 >8

Que tambm podemos representar por:

A codificao ficar ento:
mov m x y = if not(pert m 1 8)||not(pert x 1 8)||not (pert y 1 8)
then False
else if m <= 4
then if m<= 2
then if m== 1
then pmov
else smov
else if m==3
then tmov
else qmov
else if m<= 6
then if m==5
then qtmov
else sxmov
else if m == 7
then stmov
else omov
where
pmov = ...
smov = ...
tmov = ...
...

Se fizermos uma anlise das possibilidades veremos que para qualquer valor de m
o nmero mximo de avaliaes que faremos ser sempre igual a quatro! E se fosse 100
valores para m, qual seria o nmero mximo de comparaes? E para 1000? E 1000000?
79
O nmero de comparaes, seguindo este esquema, aproximadamente igual ao
logaritmo do nmero de valores na base 2. Portanto para 100 teramos 7, para 1000
teramos 10 e para um milho teramos 20. Veja que bem inferior ao que obtemos com o
esquema anterior, tambm denominado de linear. Confira a comparao na tabela abaixo.
nmero de
vaIores
esquema Iinear
(nmero mdio)
esquema binrio
(nmero mximo)
8 4 4
100 50 7
1000 500 10
1000000 500000 20
Exerccios:
1. Escreva uma funo que determina se, a partir de uma dada posio e de um
movimento vlido (1 a 8), o cavalo pode ou no realizar o movimento
desejado. Se puder, sua funo deve responder em qual linha do tabuleiro o
novo ponto, obtido aps a realizao do movimento, estar situado. Sua
funo deve se chamar movL e uma instncia dela seria movL 1 4 5 5.
2. Faa uma funo similar movL, mas agora sua funo deve se chamar
movC e deve responder a coluna correspondente da nova posio do cavalo
no tabuleiro, aps a realizao do movimento desejado.
80
10. TUPLAS
10.1. INTRODUO
At ento trabalhamos com valores elementares. Ou seja, valores atmicos, indivisveis no
que diz respeito as operaes de seu tipo de dados. Por exemplo, Frue, 523, L#23., so
valores elementares dos tipos Boolean, nteger e Float, respectivamente. No podemos,
por exemplo, nos referir, dentro da linguagem, ao primeiro algarismo do valor 523.
Dizemos que esses so tipos primitivos da linguagem. Alm desses trs, a linguagem
Haskell prov ainda o tipo c7ar. O elenco de tipos primitivos de uma linguagem pode ser
entendido como o alicerce da linguagem para a descrio de valores mais complexos, que
so denominados genericamente de $alores estruturados.
Os problemas que pretendemos resolver esto em universos mais ricos em
abstraes do que esse das linguagens. Para descrever esses mundos, precisamos usar
abstraes apropriadas para simplificar nosso discurso. Por exemplo, quando quero saber
onde algum mora, eu pergunto: Qual o seu endere3o? Quando quero saber quando um
amigo nasceu, eu pergunto: Qual a data do seu nascimento? E quando quero saber para
onde algum vai deslocar o cavalo no jogo de xadrez, eu pergunto: Qual a nova posi34o?
Os nomes endereo, data e posio designam valores estruturados. Uma data tem trs
partes: dia, ms e ano. Um endereo pode ter quatro: rua, nmero, complemento e bairro.
J a posio no tabuleiro tem duas partes, linha e coluna.
Para possibilitar a descrio de valores dessa natureza, a linguagem Haskell dispe
de um construtor denominado tupla. Podemos definir uma tupla como um agregado de
dados, que possui quantidade pr-estabelecida de componentes (dois ou mais), e onde
cada componente da tupla pode ser de um tipo diferente (primitivo ou no).
10.2. DEFINIO
A representao de uma tupla feita com a seguinte sintaxe:
(t1, t2, t3, ..., tn)
Onde cada ti um termo da tupla.
Se Fi o tipo de ti, ento o universo de uma tupla dado por:
FF ( F% x F2 x ### x Fn
Sabendo-se que os conjuntos bases dos tipos Fi so ordenados, tambm os elementos de
FF o sero.
81
Exemplos de tuplas:
Inteno Representao
1 uma data (15, 05, 2000)
2
uma posio no
tabuleiro de xadrez
(3, 8)
3 uma pessoa
("Maria Aparecida", "solteira",
(3, 02, 1970))
4 um ponto no espao (3.0, 5.2, 34.5)
5 uma carta de baralho (7, "espada")
6 validao de dados (True, 3)
7 validao de dados (False, div 5 2)
8 uma tupla formada por expresses
(x/=0 && y /= 0,
(x > y, if x*y /( 0
t7en if x > y
t7en div x y
else div y x
else 0))
9 uma tupla formada por expresses (x, y, x + y)
10.3. COMPONDO TUPLAS
Os exemplos apresentados j parecem suficientes para que tenhamos entendido como
descrever um valor do tipo tupla. Vamos ento apenas comentar sobre os exemplos e
ilustrar o uso de tuplas nas definies.
Uma tupla um valor composto. sto significa que devemos colocar entre parntesis e
separados por vrgulas os componentes deste valor. Cada componente um valor,
descrito diretamente ou atravs de expresses envolvendo operadores. Nos exemplos de
1 a 7, todos eles usam constantes. O exemplo 7 apresenta um dos valores descrito por
uma expresso. No exemplo 3, um dos termos uma outra tupla. Qualquer termo pode ser
uma tupla. Um valor pode tambm ser paramtrico, como no exemplo 9, onde temos uma
tupla de 3 termos, todos eles paramtricos, mas o terceiro depende dos dois primeiros.
Podemos dizer que esta tupla descreve todas as triplas onde o terceiro termo pode ser
obtido pela soma dos dois primeiros. No exemplo 8 podemos observar o uso de
expresses condicionais. Observa-se a tambm a descrio de um termo do tipo boolean,
atravs de uma expresso relacional combinada com operadores lgicos. Vejamos agora
alguns exemplos de uso de tuplas na descrio de valores.
ExempIo 1: Desejamos definir uma funo, para que dados 2 valores, seja produzido
uma tripla onde os dois primeiros termos so idnticos aos elementos fornecidos, em
ordem inversa, e o terceiro termo seja igual soma dos dois.

82
triplaS a b = ( b, a, a + b )
ExempIo 2: Vamos definir uma funo que produza o quociente e o resto da diviso
inteira de dois nmeros.
divInt a b = ( q, r)
where
q = div a b
r = rem a b
ExempIo 3: Voltemos definio das razes de uma equao do 2o. grau. Vimos
anteriormente que como eram duas, precisvamos definir tambm duas funes. Agora
podemos agrup-las em uma nica definio:
re2g a b c = ( x1, x2)
where
x1 = ((-b) + e)/ duploA
x2 = ((-b) - e)/ duploA
e = sqrt (b^2 - 4.0*a*c)
duploA = 2.0 * a
ExempIo 4: Voltemos aos movimentos do cavalo no jogo de xadrez. Vamos definir
uma funo que produza a nova posio, usando o primeiro movimento vlido segundo o
que se discutiu em Resolvendo Problemas - Os Movimentos do Cavalo.

qPos x y = if f x2 && f y1
then (x2,y1)
else if f x1 && f y2
then (x1,y2)
else if g x1e && f y2
then (x1e,y2)
else if g x2e && f y1
then (x2e,y1)
else if g x2e && g y1e
then (x2e,y1e)
else if g x1e && g y2e
then (x1e,y2e)
else if f x1 && f y2e
then (x1,y2e)
else (0,0)
where
x1 = x + 1
x2 = x + 2
y1 = y + 1
y2 = y + 2
x1e = x - 1
x2e = x - 2
y1e = y - 1
y2e = y - 2
f w = w <= 8
g w = w >= 1
83
Qual o valor de qPos 1 9 ? O que h de errado? Reescreva qPos de forma a
contornar o problema encontrado.
10.4. SELECIONANDO TERMOS DE UMA TUPLA
Assim com precisamos compor uma tupla na descrio dos mapeamentos de uma funo,
tambm precisamos decomp-la. Quando uma funo possui tuplas como parmetros,
para usar seus termos necessrio que se possa referenci-los.
lustraremos aqui vrias formas, utilizando a definio que soluciona o seguinte
problema:
=eseja!os deter!inar a dist0ncia entre dois pontos no plano#
1. Utilizando a clusula 87ere :
dist p1 p2 = sqrt (dx^2 + dy^2)
where
dx = x1 - x2
dy = y1 - y2
(x1,y1) = p1
(x2,y2) = p2
Observe a elegncia da definio da tupla (x1, y1). Por anlise da definio, sabemos
que o tipo de p1 e p2 tupla de 2 termos. Quando submetemos a avaliao de uma
instncia, o sistema casa p1 com um par de valores e a partir da pode determinar o valor
de cada termo de nossa tupla (x1, y1).
$ %ist &'.'('.') &".'(".')
-- o sistema casa p1 com (0.0,0.0)
-- e p2 com (5.0,5.0)
-- logo x1=0.0, y1=0.0, x2=5.0 e y2=5.0
#.'#1'#
2. Construindo funes seletoras :
prim (x,y) = x
seg (x,y) = y
dist p1 p2 = sqrt (dx^2 + dy^2)
where
dx = prim p1 - prim p2
dy = seg p1 - seg p2
Com esta abordagem, podemos generalizar e construir funes seletoras para tuplas
com uma quantidade de termos qualquer. importante destacar que tuplas com
quantidade diferente de termos precisam ter o seu prprio elenco de funes seletoras.
Em particular, para o caso acima, onde o nmero de termos 2, o prprio HUGS j
possui as funes seletoras, fst (primeiro) e snd (segundo). Poderamos t-las usado
diretamente, mas preferimos ilustrar como se constri. Podemos reescrever a soluo
usando-as.
84
dist p1 p2 = sqrt (dx^2 + dy^2)
where
dx = fst p1 - fst p2
dy = snd p1 - snd p2
3. Explicitando os componentes:
dist (x1,y1) (x2,y2) = sqrt (dx^2 + dy^2)
where
dx = x1 - x2
dy = y1 - y2
Exerccios:
1. Escreva uma funo que determina as distncias entre trs pontos no plano
cartesiano, duas a duas. Tanto os pontos dados como entrada, como as
distncias calculadas devem ser representadas por tuplas. Na resposta, cada
par de pontos deve ser exibido, seguido da distncia existente entre eles.
2. Refaa o exemplo de clculo de equaes de 2 grau, exibindo apenas as
razes reais da equao.
3. Dados a sua data de nascimento e a data atual, informe qual a sua idade.
85
11. VALIDAO DE DADOS
11.1. INTRODUO
Como sabemos, toda funo tem um domnio e um contradomnio. Em Hugs, quando
tentamos avaliar uma instncia de uma definio, usando valores fora desse domnio,
podemos receber como resposta mensagens nem sempre esclarecedoras. Quando se
trata do usurio de nosso programa, esta situao se mostra mais indesejvel ainda.
Aqueles que constroem a definio podem discernir com mais facilidade a natureza dos
problemas que ocorrem durante o seu desenvolvimento. O mesmo no se pode esperar de
algum que no tem conhecimento dos elementos internos de nossas definies.
Tipicamente os erros sero de duas naturezas. Pode ser que o tipo da instncia
esteja correto, mas nossa definio use alguma funo primitiva que no se aplica ao valor
da instncia. Por exemplo, se temos a definio:

f x y z = div x y + z
e se a submetemos a uma instncia onde ( -, teremos como resultado algo da seguinte
natureza:
? f 5 0 3
Program error: {5 `div` 0}
?
Um outro tipo de problema ocorre quando o tipo de algum parmetro da nossa
instncia no casa com o tipo inferido pelo Hugs. Por exemplo, se usamos um valor do tipo
;loat para , obtemos:
? f 5 1.0 3
ERROR: Type error in
application
*** expression : f 5 1.0 3
*** term : 1.0
*** type : Float
*** does not match : Int
Nesta seo trataremos do primeiro caso, deixando o segundo para outra
oportunidade.
11.2. CARACTERIZANDO A SITUAO
Voltemos definio anteriormente apresentada:

86
f x y z = div x y + z
Neste caso, o tipo inferido pela linguagem para os dois primeiros parmetros o tipo
:nte,er, visto que o operador di$ s se aplica a valores deste tipo. Portanto o universo
ser formado por todos os possveis ternos de valores onde os dois primeiros so do tipo
:nte,er e o ltimo, do tipo obtido pela unio dos tipos ;loat e :nte,er# Chamemo-lo de F.
Entretanto, o domnio de nossa funo no exatamente o conjunto de constantes de F,
posto que a funo no est definida para as constantes de F cujo segundo elemento
nulo.
Desejamos construir uma funo que seja uma extenso da funo original e ao
mesmo tempo lhe sirva como uma casca de proteo contra as violaes de domnio.
Precisamos escolher um contradomnio da funo estendida (fx). Um candidato natural o
contradomnio da funo original (f).
E a imagem de nossa funo, o que podemos dizer dela? Ser que ela igual ao
contradomnio? Ou ser que temos um subconjunto para o qual no exista um
mapeamento?
11.3. CASO GERAL (IMAGEM IDNTICA AO CONTRADOMNIO)
No caso geral, podemos encontrar duas situaes: ou o contradomnio idntico
imagem, ou a determinao dos elementos que no pertencem imagem pode no ser
fcil. Com isto no dispomos de valores no contradomnio que possam ser utilizados para
mapearmos os valores que violam o domnio de f. Neste caso podemos estender o
contradomnio (CD) de tal modo que o novo escolhido incorpore um valor que ser a
imagem da extenso de f.
Uma soluo geral bastante conveniente construir um novo contradomnio (NCD)
para fx (extenso de f), formado por pares onde o primeiro elemento do tipo boolean e o
segundo do contradomnio de f. Temos ento a seguinte estrutura:
NCD(fx) = (boolean, CD(f))
Para valores de x no domnio de f, teremos:
fx x = (True, f x )
Para os valores de x fora do domnio teremos:
87
fx x = (False, k )
onde 9 um valor qualquer pertencente ao contradomnio de f.
Para o nosso exemplo inicial teramos ento:
fx x y z = if invalido x y z
then (False,0)
else &*rue( f x y z)
where
invalido x y z = ...
f x y z = div x y + z
como se estivssemos criando uma casca protetora para a f#
11.4. FUNES QUE APRESENTAM PROBLEMAS EM VRIOS PARMETROS
Quando uma funo possui vrios parmetros, pode ocorrer que mais de um deles dem
origem questo que aqui levantamos. Quando isso ocorre, pode ser relevante
caracterizar a situao apropriadamente. Neste caso podemos usar um conjunto mais
variado de constantes do que as constantes booleanas, permitindo que possamos associar
com cada erro uma constante diferente.
Podemos tomar como exemplo o problema do movimento dos cavalos no jogo de
xadrez, especificamente a soluo genrica que produzimos com a funo
!o$ ! x
onde ! o nmero do movimento, x a linha atual e a coluna atual.
Os trs parmetros so vlidos apenas para o intervalo [1, 8]. Portanto !o$ no est
definida para os valores pertencentes ao subconjunto do universo formado por todas as
triplas onde pelo menos um dos elementos no pertence ao intervalo [1, 8]. Por outro lado,
o contradomnio o conjunto booleano, portanto s possui duas constantes e ambas j
esto comprometidas. Se quisermos distinguir os trs tipos de violao do domnio
(movimento invlido, posio invlida, ambos invlidos) precisaremos usar um conjunto
com pelo menos quatro constantes.
Podemos ento definir a funo "movx da seguinte forma:

mo+, m x y = if not validom
then if not validop
then (3, False)
else (1, False)
else if not validop
then (2, False)
else (0, mo+ m x y)
11.5. CASO PARTICULAR (IMAGEM DIFERENTE DO CONTRADOMNIO)
88
Suponha que existe pelo menos um elemento 9 que no pertence imagem, ou seja, a
imagem est contida no contradomnio. Podemos construir uma extenso de f de tal forma
que os elementos que no pertenam ao domnio sejam mapeados neste 9 e os demais
sejam mapeados diretamente pela f. Quando existe tal 9, nosso problema est resolvido.
Basta que o usurio saiba que, quando a avaliao resultar em 9, significa que a funo
no se aplica para aquela instncia.
Voltemos funo f introduzida anteriormente. Podemos, usando a proposta desta
seo, reescrever a sua definio, da seguinte forma:

fx x y z = if invalido x y z
then k
else f x y z
where
k = ...
invalido x y z = ...
f x y z = div x y + z
nfelizmente, para esse caso, o 9 no existe (prove!).
Voltemos ao movimento do cavalo. Nesse caso, especificamente, porque o
contradomnio original o conjunto booleano, poderamos ter tomado outro caminho.
Poderamos usar nmeros negativos para indicar os trs tipos de violao do domnio, a
constante inteira - para representar ;alse e a constante inteira % para representar Frue,
eliminando com isso a necessidade de um novo domnio formado por pares. Vejamos
como fica esta definio:

mo+, m x y = if not validom
then if not validop
then (-3)
else (-1)
else if not validop
then (-2)
else if mo+ m x y
then 1
else 0
11.6. UM EXEMPLO - RAIZES DE UMA EQUAO DO 2O. GRAU
Voltemos ao problema de determinar as razes de uma equao do segundo grau. J
sabemos que elas so duas e que podemos fazer uma nica funo para descrev-las,
usando tupla.
Sabemos ainda que o universo definido pelos tipos dos trs parmetros (a, b, c),
maior que o domnio da funo. Ou seja, a funo no est definida para instncias de a, b
e c, onde se verifica a seguinte desigualdade:
(b^2) + (4 * a * c) < 0
Precisamos, portanto de uma funo estendida.
89
re2gx a b c = &not (delta < 0)( if delta < 0
then (0,0)
else (x1, x2))
where
delta = (b ^ 2) + (4 * a * c)
x1 = ((-b) + sqrt delta) / (2 * a)
x2 = ((-b) - sqrt delta) / (2 * a)
Ou, de outra forma:
re2gx a b c = if delta < 0
then (False, (0, 0))
else (True, (x1, x2))
where
delta = (b ^ 2) + (4 * a * c)
x1 = ((-b) + sqrt delta) / (2 * a)
x2 = ((-b) - sqrt delta) / (2 * a)
Exerccios
1. Explique por que no existe o valor k que apie a definio da funo fx;
2. Faa uma funo estendida para f x y = 1/(x+ y)
3. Fornea dois exemplos de funes para as quais possvel criar uma funo
estendida na qual se possa usar constantes que no pertencem garantidamente
imagem da funo original
90
12. LISTAS
12.1. INTRODUO
A maioria dos itens de informao de nosso interesse est agrupada, dando origem a um
conceito muito importante para a resoluo de problemas, o agrupamento.
Freqentemente estamos interessados em manipular esses agrupamentos para extrair
informaes, definir novos itens ou avaliar propriedades desses agrupamentos.
Tratamos anteriormente das tuplas, que so agrupamentos de tamanho predefinido e
heterogneo, ou seja, cada elemento que participa do agrupamento pode ser de um tipo
diferente. Agora estamos interessados em explorar outro tipo de agregao, as listas. Este
novo tipo, em HUGS, caracteriza-se por agregar quantidades variveis de elementos
desde que todos eles sejam de um mesmo tipo.
Vivemos cercados de listas. Elas esto em qualquer lugar onde precisamos registrar
e processar dados. Vejamos alguns exemplos:
1. Lista de nmeros pares;
2. Lista dos livros lidos por uma pessoa;
3. Lista dos amigos que aniversariam em um dado ms;
4. Lista dos presidentes corruptos;
5. Lista dos vereadores decentes;
6. Lista das farmcias enganadoras;
7. Lista das disciplinas que j cursei;
8. Lista dos lugares que visitei;
9. Lista dos nmeros feios;
10. Lista dos nmeros primos;
11. Lista das posies para as quais um cavalo pode se deslocar;
12. Lista das palavras de um texto;
13. Lista dos erros provocados pelo Windows;
14. Lista dos prmios Nobel ganhos pelo Bertrand Russel;
15. Lista dos ttulos conquistados pelo Nacional Futebol Clube;
16. Listas dos fun+s compostos pelo Noel Rosa.
Destas, algumas so vazias, outras so finitas e algumas infinitas.
12.2. CONCEITOS BSICOS : Uma lista uma seqncia de zero ou mais elementos de
um mesmo tipo.
Entende-se por seqncia uma quantidade qualquer de itens dispostos linearmente.
Podemos representar uma lista pela enumerao dos seus elementos, separados por
vrgulas e cercados por colchetes.
[ e%, e2, .., en]
Por exemplo:
91
1. [ ]
2. [1,3,5,7,9]
3. ['a', 'e', 'i', 'o', 'u']
4. [(22,04,1500), (07,09,1822), (31,03,1964)]
5. [[1,2,5,10], [1,11], [1,2,3,4,6,12], [1,13], [1,2,7,14], [1,3,5,15]]
importante ressaltar que em uma lista podemos falar do primeiro elemento, do
quinto, do ensimo, ou do ltimo. Ou seja, h uma correspondncia direta entre os
nmeros naturais e a posio dos elementos de uma lista.
Este ltimo fato nos lembra de um equvoco freqente, que queremos esclarecer de
sada. A ordem que se adota em listas, por ser baseada nos nmeros naturais, comea do
zero. Ou seja, o primeiro elemento de uma lista tem o nmero de ordem igual a zero.
Por exemplo, na relao acima apresentada, a primeira lista vazia. Na lista do item
4 o elemento de ordem 1 a tupla (07, 09,1822) e na lista do item 5, o elemento de ordem
zero (0) a lista [1,2,5,10].
Quanto ao tipo, podemos dizer que a segunda lista uma lista de nmeros, a terceira
uma lista de caracteres, a quarta uma lista de triplas de nmeros e a quinta uma lista
de listas de nmeros. Qual ser o tipo da primeira lista?
Uma lista vazia de natureza polimrfica, isto , seu tipo depende do contexto em
que seja utilizada, como veremos em momento oportuno.
12.3. FORMAS ALTERNATIVAS PARA DEFINIO DE LISTAS
Alm da forma bsica, acima apresentada, tambm conhecida como enumerao, onde
explicitamos todos os elementos, dispomos ainda das seguintes maneiras: definio por
intervalo, definio por progresso aritmtica e definio por compreenso. As duas
primeiras formas so apresentadas a seguir e a terceira, posteriormente.
Definio por IntervaIo
De uma forma geral, podemos definir uma lista explicitando os limites inferior e
superior de um conjunto conhecido, que possua uma relao de ordem entre os
elementos, no seguinte formato:
[<limite inferior> .. <limite superior>]
Exemplos: abaixo listamos algumas submisses de listas definidas por intervalo e as
correspondentes respostas do sistema HUGS.
92
1 -relu%e> [1..5]
[1,2,3,4,5]
! -relu%e> [-2..2]
[-2,-1,0,1,2]
3 -relu%e> [10..5]
[]
4 -relu%e> [-5.0..5.0]
[-5.0,-4.0,-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0,4.0,5.0]
" -relu%e> [-1..-5]
ERROR: Undefined variable "..-"
6 -relu%e> [-1..(-5)]
[]
# -relu%e> [1.6..10.0]
[1.6,2.6,3.6,4.6,5.6,6.6,7.6,8.6,9.6]
. -relu%e> [1.5..10.0]
[1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5,10.5]
Podemos observar aqui algumas aparentes surpresas: no exemplo 4 podemos observar
que o HUGS considera sempre o intervalo de uma unidade entre os elementos da lista
definida. No exemplo 5, temos uma questo de ambigidade, 0 sinal de menos logo aps
os dois pontos no entendido e o sistema sinaliza erro. O exemplo 6 contorna essa
dificuldade. Deixo ao leitor buscar explicao para o que ocorre com os exemplos 7 e 8.
Definio por Progresso Aritmtica
Podemos definir qualquer progresso aritmtica por uma lista utilizando a seguinte
notao:
[<1o. termo>, <2o. termo> .. <limite superior>]
Exemplos: observemos as definies a seguir e as respectivas respostas do sistema
HUGS. Podemos perceber que dependendo do segundo termo da definio o sistema
interpreta a P.A. como crescente ou decrescente.
1 -relu%e> [1,2..6]
[1,2,3,4,5,6]
! -relu%e> [-5,2..5]
[-5,2]
3 -relu%e> [-5,2..15]
[-5,2,9]
4 -relu%e> [-5,2..16]
[-5,2,9,16]
" -relu%e> [1,1.1 .. 2]
[1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0]
6 -relu%e> [6,5..0]
[6,5,4,3,2,1,0]
# -relu%e> [5,6..5]
[5]
. -relu%e> [3,7..1]
[]
93
12.4. OPERAES BSICAS
As listas, como j dissemos, so elementos da linguagem que podemos utilizar para
descrever valores estruturados. Como nos demais tipos da linguagem, valores descritos
por listas podem e devem ser usados na descrio de novos valores atravs da utilizao
de operaes definidas sobre eles. A seguir so apresentadas algumas dessas operaes.
eIem : avalia se um determinado elemento membro de uma lista.
eIem <elemento> <lista>
ExempIos:
Main> elem 5 [-5..15]
True
Main> elem (-10) [-5..15]
False
Main> elem 20 [-5..15]
False
Main> elem 15 [-5..15]
True
Iength : descreve o tamanho de uma lista.
Iength <lista>
ExempIos:
-relu%e>length [1..100]
100
(2528 reductions, 3442 cells)
-relu%e>length [1..100] + length [1..100]
200
(5050 reductions, 6873 cells)
-relu%e> a + a where a = length [1..100]
200
(2530 reductions, 3442 cells)
indexao : podemos descrever cada termo de uma lista como um novo valor. Para
tanto basta indicarmos a posio do elemento dentro da lista, considerando que o primeiro
elemento tem a ordem zero.
<lista>!!<ndice>
ExempIos:
1 -relu%e> [3,4,6,74,45]//0
3
! -relu%e> [3,4,6,74,45]//4
45
3 -relu%e> [1,5..20]//3
13
4 -relu%e> [[[1],[2,3,4]]]//0//1//2
4
" -relu%e> [3,4,6,74,45]//3
74
94
6 -relu%e> [3,4,6,74,45]//3 + [2,3]//0
76
# -relu%e> [3,4,6,74,45]//(0+1)
4
. -relu%e> [3,4,6,74,45]//(i+j) where i=3; j=0
74
0 -relu%e> [84,76,23,124,763,23]//([0,1,2,3]//2)
23
1' -relu%e> [1,5..20]!!5
Program error: Prelude.!!: index too large
concat : descreve uma nova lista obtida pela concatenao de uma lista de listas.
concat )lista de listas*
ExempIos:
1 -relu%e>1on1at [[1..5],[1,10..100],[9]]
[1,2,3,4,5,1,10,19,28,37,46,55,64,73,82,91,100,9]
(473 reductions, 747 cells)
! -relu%e>1on1at [[1]]
[1]
(25 reductions, 35 cells)
3 -relu%e> length (1on1at [[1..5],[1,10..100],[9]])
18
(451 reductions, 638 cells)
4 -relu%e> 1on1at [[length [10,87..500]], [length
[10,87,500]]]
[7,3]
(228 reductions, 309 cells)
" -relu%e> length (1on1at [[length [10,87..500]],
[length [10,87,500]]])
2
(30 reductions, 35 cells)
Pode tambm ser usado com a sintaxe infixada usando o operador ++
ExempIos:
1 -relu%e> [1] ++ [1]
[1,1]
(33 reductions, 48 cells)
! -relu%e> [1] ++ []
[1]
(23 reductions, 33 cells)
3 -relu%e> [ ] ++ [ ]
ERROR: Cannot find "show" function for:
*** Expression : [] ++ []
*** Of type : [a]
4 -relu%e> [1..5] ++ [1,10..100] ++ [9]
[1,2,3,4,5,1,10,19,28,37,46,55,64,73,82,91,100,9]
(467 reductions, 738 cells)
construtor : descreve uma nova lista onde o primeiro termo um elemento dado e
os demais so os componentes de uma lista tambm dada.
95
<elemento> : <lista>
ExempIos:
1 -relu%e> 3: [4,5,6]
[3,4,5,6]
! -relu%e> [3]:[[4,5,6]]
[[3],[4,5,6]]
3 -relu%e> [3: [4,5,6]]
[[3,4,5,6]]
4 -relu%e> [3: [4,5,6]]!!0
[3,4,5,6]
" -relu%e> [3: [4,5,6]]!!0!!3
6
head : descreve o primeiro elemento de uma lista.
taiI : descreve uma sublista contendo todos os elementos, exceto o primeiro elemento
de uma lista dada.

Teorema importante:
head xs : (taiI xs) = xs

Iast : descreve o ltimo elemento de uma lista..
init : descreve uma sublista contendo todos os elementos, exceto o ltimo elemento
de uma lista dada.

Teorema importante:
init xs ++ [last xs] = xs
mportante: As funes head, last, init e tail no possuem em seu domnio a lista
vazia. Portanto ela no deve ser instncia de avaliao para qualquer uma delas.
<elemento> : <lista>
ExempIos:
96
1 Hugs> head [1,2,3,4,5,6]
1
! Hugs> tail [1,2,3,4,5,6]
[2,3,4,5,6]
3 Hugs> tail [1,2,3,4,5,6]
[2,3,4,5,6]
4 Hugs> last [1,2,3,4,5,6]
6
" Hugs> init [1,2,3,4,5,6]
[1,2,3,4,5]
6 Hugs> x == (head x : tail x) where x = [10..15]
True
# Hugs> init [10..15] ++ tail [10..15]
[10,11,12,13,14,11,12,13,14,15]
12.5. DEFINIO POR COMPREENSO
Uma lista pode ser descrita atravs da enumerao de seus elementos, como j
vimos atravs de vrios exemplos. Esta forma tambm denominada de definio por
extenso, visto que todos os componentes precisam ser explicitados.
Podemos tambm descrever listas atravs das condies que um elemento deve
satisfazer para pertencer a ela. Em outras palavras, queremos descrever uma lista atravs
de uma inteno. Esta forma anloga que j conhecemos para descrio de conjuntos.
Por exemplo, usual escrever a notao abaixo para descrever o conjunto formado pelo
quadrado dos nmeros naturais menores que 10.
P = {quadrado de x | x naturaI e menor que 10}
ou ainda mais formalmente,
P = { x
2
| x pertence a N e x <10}
Podemos observar, no lado direito da definio, que ela formada por duas partes. A
primeira uma expresso que descreve os elementos, usando para isso termos variveis
que satisfazem condies de pertinncia estabelecidas pela segunda parte.
expresso x^2
varivel x
pertinncia x pertence a N e x <10
Em nosso caso, no estamos interessados em descrever conjuntos e sim listas. E
isso tem algumas implicaes prticas. Por exemplo, em um conjunto a ordem dos
elementos irrelevante, para listas no. bom lembrar ainda que em uma lista, o mesmo
valor pode ocorrer varias vezes, em diferentes posies.
A sintaxe que usaremos a seguinte:
[ <expresso> | <pertinncia> ]
97
Onde:
<expresso> - expresses usuais em Haskell para definio de valores, inclusive
condicionais.
<pertinncia> - descrio dos elementos a serem considerados para avaliao da
<expresso>.
A pertinncia formada por uma seqncia de qualificadores de dois tipos de
construo: os geradores e os predicativos. Os geradores descrevem uma lista de onde se
originam os elementos a serem considerados, usando a sintaxe:

2termo> 2- 2lista>
Por exemplo, vejamos a descrio da lista dos quadrados dos nmeros menores que
5.
Prelude> [x^2| x<-[0..4]]
[0,1,4,9,16]
Os predicativos so expresses descrevendo valores booleanos, envolvendo termos
j definidos anteriormente (inclusive por geradores).
Vejamos o exemplo a seguir, onde descrevemos uma sublista de nmeros mpares,
tendo como origem de gerao uma lista definida por uma Progresso Aritmtica.
Prelude> 3, 4 ,2-31(4..1''5(o%% ,5
[1,7,13,19,25,31,37,43,49,55,61,67,73,79,85,91,97]
importante destacar que as expresses de pertinncia so avaliadas da esquerda
para direita.
Por exemplo, se na expresso acima, primeiro colocssemos a expresso booleana
"odd x", o sistema acusaria um erro, visto que ao tentar a avaliar "odd x", a varivel "x"
ainda no estaria definida.
Prelude> 3, 4 o%% ,( ,2-31(4..1''55
ERROR: Undefined variable "x"
sto s ocorre porque o sistema usa uma ordem pr-definida!
Vejamos como usar este novo conceito na escrita de novos scripts. A seguir
apresentamos a definio de trs novas funes. A primeira, sIpares, define uma sublista
formada pelos quadrados dos elementos pares de uma lista dada. A segunda, Imenor,
define uma sublista formada pelos elementos de uma dada lista, que so menores que um
elemento fornecido. A terceira, pmaioresk, ilustra o uso da clusula if-then-eIse para a
gerao de elementos de uma lista.
98
-- Dada uma lista 'xs' defina uma sublista formada
-- pelo quadrado dos elementos que so pares
--
slpares ,s = 3,6! 4 ,2- ,s( e+en ,5
Main> :l preparalista.txt
Reading file "preparalista.txt":
Hugs session for:
E:\HUGS98\lib\Prelude.hs
preparalista.txt
Main> slpares 31(4.."'5
[16,100,256,484,784,1156,1600,2116]
Main> slpares 334(6#(00(!3(1!(3(6#(005
[1156,144]
--
-- Determinar a sublista de elementos menores que 'x'
-- em uma lista 'xs
--
lmenor , ,s = 3 7 4 7 2-,s( 7 2 ,5
...
Main> lmenor 4" 31("(6(.6(34(#6(1!(34(.6(005
[1,5,6,34,12,34]
Main> lmenor 1 31("(6(.6(34(#6(1!(34(.6(005
[]
Main> lmenor 1'' 31("(6(.6(34(#6(1!(34(.6(005
[1,5,6,86,34,76,12,34,86,99]
--
-- Determinar a lista de elementos gerados condicionalmente
-- a uma constante dada k.
pmenores8 8 ,s = 3 if , > 8 then ,! else , 9 ! 4 , 2-,s5
...
Main> pmenores8 3' 31("(6(.6(34(#6(1!(34(.6(005
[1,25,36,88,36,78,144,36,88,101]
Quando mais de um gerador utilizado, devemos levar em conta que para cada
elemento do gerador mais a esquerda sero gerados todos os elementos dos geradores
subseqentes. Vejamos o exemplo a seguir onde se descreve uma lista de pontos do
plano cartesiano, localizados no primeiro quadrante e delimitado pelas ordenadas 3 e 5.
99

--
-- Determinar a lista dos pontos do plano dentro da
-- regiao definida pela origem, a cordenada (eixo y)
-- 5 e a abscissa (eixo x) 3.
--
pontos = 3 &,(7) 4 , 2- 3'..35( 7 2- 3'.."55
...
Main> pontos
3(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),
(1,0),(1,1),(1,2),(1,3),(1,4),(1,5),
(2,0),(2,1),(2,2),(2,3),(2,4),(2,5),
(3,0),(3,1),(3,2),(3,3),(3,4),(3,5)5
Entre dois geradores podemos usar predicativos, como se observa no exemplo a
seguir.
--
-- Determinar a lista dos pontos do plano dentro da
-- regiao definida pela origem, a cordenada (eixo y)
-- 5 e a abscissa (eixo x) 3. Considere apenas os
-- pontos onde x impar e y par.
--
pontos1 = 3 &,(7) 4 , 2- 3'..35( o%% ,( 7 2- 3'.."5( e+en 7 5
...
Main> pontos1
[(1,0),(1,2),(1,4),(3,0),(3,2),(3,4)]
12.6. DEFINIO POR COMPREENSO - EXPLORANDO DETALHES
Vamos explorar um problema onde exista mais riqueza de detalhes quanto ao uso de
predicativos.
Determinar os pares de valores, onde:
o primeiro mltiplo do segundo;
o primeiro dado pelos elementos impares de uma P.A de primeiro termo
igual a 1, a razo igual 3 e o ultimo termo menor ou igual a 100;
o segundo termo dado pelos elementos de uma P.A de primeiro termo igual
a 1, a razo igual 4 e o ultimo termo menor ou igual a 50;
um dos dois diferente da unidade;
os dois termos so diferentes.
100
--
-- A funo paresE, traduz literalmente o enunciado.
-- As P.A.'s so realizadas diretamente pelo mecanismo
-- para definio de P.A. embutido na linguagem.
-- Os predicativos foram inseridos na posio em que
-- suas variveis j esto instanciadas.
--
pares:1 = 3 &,(7) 4 , 2- 31(4..1''5(
o%% ,(
7 2- 31(".."'5(
&,;=1 44 7;= 1)(
,;=7(
mo% , 7 == '5
...
Main> pares:1
3(7,1),(13,1),(19,1),(25,1),(25,5),(31,1),(37,1),
(43,1),(49,1),(55,1),(55,5),(61,1),(67,1),(73,1),
(79,1),(85,1), (85,5),(85,17),(91,1),(91,13),(97,1)5
Vejamos algumas observaes sobre a soluo acima apresentada:
o predicado odd poderia ser colocado em qualquer lugar mais a frente, entretanto o
desempenho cairia, visto que iramos produzir valores desnecessrios para "y";
a expresso (x/=1 || y/= 1) desnecessria visto que s ser falsa quando ambos, x
e y, forem iguais a 1, mas nesse caso eles sero iguais e portanto falsificariam a
expresso a seguir x/=y;
podemos reescrever a expresso x <- [1,4..100] de tal maneira que gere apenas
valores mpares e assim descartar a expresso odd x. Para tanto basta mudar a
P.A. para [1,7..100];
pode-se observar que os valores de y que interessam so sempre menores que os
de x ( j que y divisor de x). Portanto, a segunda P.A poderia ser substituda por
[1,5..(x-1)]. Acontece que agora poderemos geram valores para y maiores que 50 e
isto no interessa. O que fazer? Que tal substitu-la por:
[1, 5..(if x < 50 then (x-1) eIse 50)]
Eis ento uma nova verso para nossa funo:
pares:! = 3 &,(7) 4 , 2- 31(#..1''5(
7 2- 31("..&if , 2 "'
then &,-1)
else "')5(
,;=7(
mo% , 7 == '5
Podemos agora refletir sobre uma possvel generalizao para a nossa funo,
considerando-se duas listas quaisquer. Neste caso, o esforo realizado para melhorar o
101
desempenho seria em vo porque no conhecemos a priori a natureza das duas listas.
Nossa funo poderia ser:
pares:3 ,s 7s = 3 &,(7) 4 , 2- ,s(
o%% ,(
7 2- 7s(
,;=7(
mo% , 7 == '5
Apenas a expresso (x/=1 || y/= 1) poderia ser eliminada. O objetivo de nossa
verso original poderia ser obtido pelo uso da nova funo aplicada s listas especficas.
Conforme se observa a seguir:
Main> pares:3 31(4..1''5 31(".."'5
[(7,1),(13,1),(19,1),(25,1),(25,5),(31,1),(37,1),(43,1),
(49,1),(55,1),(55,5),(61,1),(67,1),(73,1),(79,1),(85,1),
(85,5),(85,17),(91,1),(91,13),(97,1)]
&16.#. re%u1tions( !300! 1ells)

Agora podemos ainda inspecionar o que de fato acontece com o desempenho das
trs verses.

Main> pares:1
[(7,1),(13,1),(19,1),(25,1),(25,5),(31,1),(37,1),(43,1),
(49,1),(55,1),(55,5),(61,1),(67,1),(73,1),(79,1),(85,1),
(85,5),(85,17),(91,1),(91,13),(97,1)]
&!!.04 re%u1tions( 3!!1' 1ells)
Main> pares:!
[(7,1),(13,1),(19,1),(25,1),(25,5),(31,1),(37,1),(43,1),
(49,1),(55,1),(55,5),(61,1),(67,1),(73,1),(79,1),(85,1),
(85,5),(85,17),(91,1),(91,13),(97,1)]
&1"1!4 re%u1tions( !!'14 1ells)

Coloquemos os valores obtidos em uma tabela.
verso redues c!lulas
"ares#$ ((+,4 3((1-
"ares#% 1.1(4 ((-14
"ares#& 1$+'+ (3,,(
Aqui podemos constatar que a verso paresE3, bastante similar a paresE1, a menos
da generalizao, possui eficincia bem superior. Lembre-se que a nica diferena a
eliminao da comparao dos dois termos com o valor 1.
Para ver o que est acontecendo, vamos construir ainda uma outra verso, similar a
paresE1, eliminando a comparao citada e descrevendo as P.A.'s fora dos geradores,
102
assimilando-se assim verso paresE3. Veja que com isso a nova verso, que obtivemos
partindo de paresE1, possui eficincia similar a paresE3. Confirma-se ento a observao
de que a definio de listas dentro dos geradores produz perdas.

pares:4 = 3 &,(7) 4 , 2- ,s(
o%% ,(
7 2- 7s(
,;=7(
mo% , 7 == '5
here
,s = 31(4..1''5
7s = 31(".."'5
...
main> pares:4
[(7,1),(13,1),(19,1),(25,1),(25,5),(31,1),(37,1),(43,1),
(49,1),(55,1),(55,5),(61,1),(67,1),(73,1),(79,1),(85,1),
(85,5),(85,17),(91,1),(91,13),(97,1)]
&16.#. re%u1tions( !300! 1ells)
12.7. OPERAES PARA DETERMINAR SUBLISTAS
Existem algumas operaes predefinidas no Haskell para descrevermos sublistas de uma
lista dada. Nada que no possa ser feito com o que j apresentamos at aqui. Entretanto o
seu uso pode ajudar na prtica do reuso e contribuir bastante para a clareza de um
programa.
Grupo I - Considerando um tamanho especificado
take k xs - define uma lista com os k primeiros elementos de uma lista xs.
drop k xs - define uma lista com os elementos de xs, a partir do elemento seguinte aos k
primeiros.
Vejamos a ilustrao a seguir.
Prelude> ta8e 3 [0..10]
3'(1(!5
(156 reductions, 221 cells)
Prelude> %rop 3 [0..10]
33(4("(6(#(.(0(1'5
(358 reductions, 513 cells)
Prelude> 3,s//i 4 i 2-3'..&8 - 1)55
here ,s = 3'..1'5< 8 = 3
3'(1(!5
(249 reductions, 336 cells)
Prelude> 3,s//i 4 i 2-38..length ,s - 155
here ,s = 3'..1'5< 8 = 3
33(4("(6(#(.(0(1'5
(1591 reductions, 2072 cells)
Prelude> &ta8e 3 31..1'5 99 %rop 3 31..1'5) == 31..1'5
*rue
(658 reductions, 980 cells)
103
Na verdade podemos escrever uma descrio geral para take e drop usando listas
por compreenso. Alm disso, sabemos que a concatenao de take e drop para um certo
k, aplicado uma lista xs, igual prpria lista.
take k xs = [xs!!i | i <-[0..(k - 1)]]
drop k xs = 3,s//i 4 i 2-38..length ,s - 155
vale o seguinte teorema:
take k xs ++ drop k xs = xs
Grupo II - Considerando a satisfao de um predicado pred. VaIe Iembrar que um
predicado uma funo cujo vaIor resuItante do tipo booIean.
takeWhiIe pred xs - define uma lista com os primeiros elementos de uma lista xs
satisfazendo o predicado pred.
dropWhiIe pred xs - define uma lista com os elementos de xs, a partir do primeiro
elemento que no satisfaz o predicado pred.
Vejamos a ilustrao a seguir.
Prelude> takeWhile even [1..10]
[]
Prelude> takeWhile odd [1..10]
[1]
Prelude> dropWhile odd [1..10]
[2,3,4,5,6,7,8,9,10]
Prelude> dropWhile even [1..10]
[1,2,3,4,5,6,7,8,9,10]
Prelude> takeWhile (<5) [1..10]
[1,2,3,4]
Prelude> dropWhile (<5) [1..10]
[5,6,7,8,9,10]
Prelude> takeWhile (<5) [1..10] ++
dropWhile (<5) [1..10] == [1..10]
True

104
13. RESOLVENDO PROBLEMAS COM LISTAS
Neste captulo desenvolveremos a soluo para alguns problemas mais complexos. A
inteno apresentar o uso de estratgias de propsito geral que podem ser teis na
resoluo de novos problemas. Discutimos tambm algumas questes relativas ao
desempenho das solues.
13.1 PROBLEMA 1 : =ada u!a lista, deter!ine o seu !aior ele!ento
Comecemos por definir, usando a linguagem de conjuntos, quem este elemento.
Dizemos que k o maior elemento de um conjunto C, se e somente se, o subconjunto
de C formado por todos os elementos maiores que k vazio.
Em linguagem de lista isto equivale a dizer que se C uma lista, a sublista de C
formada pelos caras de C maiores que k vazia.
Vejamos como fica a codificao em Haskell.
--
-- definindo uma funo para determinar, em uma lista,
-- a sublista dos elementos maiores que um dado x
--
maiores x xs = [ y | y <- xs, y > x]
--
--
-- Em listas, podemos ter elementos repetidos, e em particular
-- podemos ter vrios exemplares do maior elemento.
-- Chamemos esses caras de os "maiorais da lista".
-- Vamos construir uma funo para descrev-los.
--
maiorais xs = [ k | k <- xs, maiores k xs == [] ]
--
-- Como eles so todos idnticos podemos tomar o primeiro deles
-- como soluo de nosso problema.
--
maximo xs = head (maiorais xs)
--
13.2 PROBLEMA 2: =ada u!a lista, $erifique se ela n4o decrescente#
Como aquecimento, vamos considerar listas de nmeros e a noo usual de ordem no
decrescente. Antes de programar, vamos resgatar a definio de seqncias no
decrescentes.

=efini34o: Uma seqncia S est em ordem no decrescente se e somente se
qualquer um de seus elementos menor ou igual aos seus sucessores. Em outras
palavras, podemos dizer que a coleo de elementos de S que so maiores que seus
sucessores vazia.

105
--
-- lista dos maiores que os sucessores
--
lms1 xs = [ xs!!i | i <-[0..length xs - 2],
j <-[i+1..length xs - 1],
xs!!i > xs!!j]
--
-- a sequncia est ordenada se a lista dos elementos
-- que so maiores que algum sucessor vazia
--
ord1 xs = (lms1 xs) == []
...
Main> or%1 31..1'5
True
(10801 reductions, 13891 cells)
Main> or%1 31'(0..15
False
(405 reductions, 571 cells)
13.3. DISCUTINDO EFICINCIA: Observando a avaliao da funo ord1, apresentada
na seo anterior, para uma lista j ordenada, a lista [1,2,3,4,5,6,7,8,9,10], constatamos
um nmero muito grande de redues. Convm questionar os motivos.
Main> or%1 31..1'5
True
(10801 reductions, 13891 cells)
Main> or%1 31'(0..15
False
(405 reductions, 571 cells)
Em geral os motivos para um baixo desempenho so de duas naturezas: explorao
inadequada das propriedades do problema e escolha inadequada dos mecanismos da
linguagem. A seguir fazemos uma pequena explorao desses dois aspectos.
13.3.1. EXPLORANDO PROPRIEDADES DO PROBLEMA - Analisando a nossa definio
anterior constatamos que ela diz mais do que precisamos. Ela avalia cada elemento com
respeito a todos sucessores. Na verdade, nossa definio pode ser melhorada. Basta
saber que cada elemento tem que ser menor ou igual ao seu sucessor imediato. Vamos
reescrever a nossa definio:
=efini34o : Uma seqncia S est em ordem no decrescente se e somente se
qualquer um de seus elementos menor ou igual ao seu sucessor imediato. Em outras
palavras, podemos dizer que a coleo de elementos de S que so maiores que seus
sucessores imediatos vazia.

Vejamos ento a implementao em Haskell e sua aplicao s mesmas instncias
do problema:
106
--
-- lista dos elementos maiores que o sucessor imediato
--
lms2 xs = [ xs!!i | i <-[0..length xs - 2],
xs!!i > xs!!(i+1)]
--
ord2 xs = (lms2 xs) == []
...
Main> or%! 31..1'5
True
(2236 reductions, 2885 cells)
Main> or%! 31'(0..15
False
(314 reductions, 449 cells)
Podemos observar uma queda no nmero de reduKes da ordem de 79%!!! Para o
pior caso, ou seja, quando todos os elementos satisfazem a propriedade estabelecida. No
melhor caso, onde o primeiro j no satisfaz a propriedade, a queda foi da ordem de 22%.
Na utilizao de clulas, os ganhos foram da mesma ordem.
13.3.2. EXPLORANDO OS MECANISMOS DA LINGUAGEM - Uma outra investida que
podemos fazer com respeito ao uso adequado dos mecanismos da linguagem. As
solues acima apresentadas processam as listas atravs de ndices, ou seja, fazem um
acesso aleatrio aos elementos da lista. Como j foi discutido, o acesso seqencial possui
realizao mais eficiente.
--
-- Para manusear os pares de adjacentes, ao
-- invs de usar ndices, usemos a funo =ip
-- aplicada a um par de listas construdas com base em ,s
-- a)lista formada pelos elementos de xs, exceto o ltimo,
-- que pode ser obtida com a funo init;
-- b)lista formada pelos elementos de xs, exceto o primeiro,
-- que pode ser obtida com a funo tail.
-- Com isso obtemos uma lista formada pelos pares adjacentes.
--
a%>a1entes ,s = =ip &init ,s) &tail ,s)
...
Main> a%>a1entes 31..1'5
[(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10)]
(414 reductions, 822 cells)
Main> a%>a1entes 31'(0..15
[(10,9),(9,8),(8,7),(7,6),(6,5),(5,4),(4,3),(3,2),(2,1)]
(364 reductions, 667 cells)
--
-- A nova funo para definir lista dos maiores
-- que os sucessores. Agora trabalharemos com os pares
--
lms3 ps = [ (x,y) | (x,y) <- ps, x>y]
--
-- A nova verso de 'ord'
--
ord3 xs = lms3 (adjacentes xs) == []
107
...
Main> or%3 31..1'5
True
(313 reductions, 483 cells)
Main> or%3 31'(0..15
False
(82 reductions, 145 cells)
O ganho obtido para a instncia considerada foi de 86% no nmero de redues e de
83% no nmero de clulas utilizadas, com respeito segunda definio.
Exerccios:
1. Verificar se uma cadeia de caracteres representa um nmero inteiro positivo.
2. Dada uma lista l, contendo uma quantidade igual de nmeros inteiros pares e
mpares (em qualquer ordem), defina uma funo que, quando avaliada, produz uma lista
na qual esses nmeros pares e mpares encontram-se alternados.
3. Dada uma lista xs, fornecer uma dupla contendo o menor e o maior elemento
dessa lista.
4. Dadas duas listas de elementos distintos, determinar a unio delas.
108
14. PARADIGMA APLICATIVO
14.1. INTRODUO: A descrio de funes, como acontece com outras formas de
representao de conhecimento, admite vrios estilos. Dependendo do problema que
estamos tratando, um estilo pode ser mais conveniente que outros. Podemos dizer que
influi muito na escolha, o quanto desejamos ou necessitamos, falar sobre como computar
uma soluo. A descrio de solues tem um espectro de operacionalidade que vai do
declarativo at o procedural, em outras palavras, do que desejamos computar ao como
queremos computar.
Uma situao que ocorre com freqncia na descrio de funes a necessidade
de aplicar uma funo, de forma cumulativa, uma coleo de elementos. Em outras
palavras, desejamos generalizar uma operao para que seu uso se estenda a todos os
elementos de uma lista. Chamemos este estilo de paradigma aplicativo.
Por exemplo, suponha que desejamos obter a soma de todos os elementos de uma
lista. A operao adi34o (+) segundo sabemos, de natureza binria, ou seja, opera sobre
dois elementos produzindo um terceiro. Para operar sobre todos os elementos de uma lista
de forma a obter a soma total, podemos oper-los dois a dois, obtendo com isso resultados
intermedirios, que por sua vez podero ser novamente operados e assim sucessivamente
at que se obtenha o resultado final. Observemos o processo para uma instncia:
M+ter a so!a dos ele!entos da lista N5, O, 3, L, %5, %&P
Podemos tomar os pares de elementos, primeiro com segundo, terceiro com quarto
e assim sucessivamente.
expresso nova expresso reduo
+ [5, 9, 3, 8, 15, 16] + [14, 3, 8, 15, 16]
5 + 9 = 14
+ [14, 3, 8, 15, 16] + [14, 11, 15, 16]
3 + 8 = 11
+ [14, 11, 15, 16] + [14, 11, 31]
15 + 16 = 31
+ [14, 11, 31] + [25, 31]
14 + 11 = 25
+ [25, 31] + [56]
25 + 31 = 56
+ [56]
56
A escolha dos pares, no caso da adio, no importa. As redues poderiam ser
aplicadas em qualquer ordem, visto que a operao adio comutativa. Se, pode ser
qualquer uma, ento podemos estabelecer uma ordem, como por exemplo, da esquerda
para a direita, usando em cada nova reduo o elemento resultante da reduo anterior.

Expresso nova expresso Reduo
+ [5, 9, 3, 8, 15, 16] + [14, 3, 8, 15, 16]
5 + 9 = 14
109
+ [14, 3, 8, 15, 16] + [17, 8, 15, 16]
14 + 3 = 17
+ [17, 8, 15, 16] + [25, 15, 16]
17 + 8 = 25
+ [25, 15, 16] + [40, 16]
25 + 15 = 40
+ [40, 16] + [56]
40 + 16 = 56
+ [56]
56
Em DQR> existe um operador que permite a descrio de computaes desta
natureza. Este operador denomina-se foldl. A sua utilizao requer ainda que seja
indicado um $alor especial para a operao considerada. Este elemento tomado como
ponto de partida para as redues, ou seja, a primeira aplicao da operao sobre o
$alor especial e o primeiro elemento da lista.
Eis a sintaxe:
foIdI <operao> <valor especial> <lista>
A ordem estabelecida para as redues semelhante ilustrao acima, ou seja,
caminha-se da esquerda para direita, usando o resultado da reduo anterior para a nova
reduo.
expresso nova expresso
foldl op $e [x0, x1, x2,...,xn] op [(op ve x0), x1, x2,...,xn]
op [(op (op ve x0) x1), x2,...,xn] op [op((op (op ve x0) x1) x2),...,xn]
op [op(op((op (op ve x0) x1) x2)... xn)] op(op((op (op ve x0) x1) x2)... xn)
Merece aqui um destaque, foldl na verdade um funo, com 3 parametros, sendo
que um deles uma outra funo. Dizemos neste caso que foldl uma funo de segunda
ordem.
O tipo da operao tem que ser:
2alfa> -> 2?eta> -> 2?eta>
onde :
<alfa> pode ser do mesmo tipo de <beta>;
<beta> tem que ser do tipo dos componentes
da lista;
o valor especial do tipo <alfa>
Vejamos ento a definio do operador su! disponvel no HUGS e cujo objetivo a
descrio da soma dos elementos de uma lista.

sum xs = fol%l (+) 0 xs
OBS:
110
1. Os operadores infixados so indicados entre parntesis.
2. O valor especial o zero, visto que no desejamos que o valor especial
modifique o resultado da soma de todos os elementos. Entretanto, ele joga
um papel muito especial quando a lista for vazia.
prelude> sum []
0
3. Em exemplos futuros veremos outros usos para o valor especial.
14.2. ALGUMAS OPERAES IMPORTANTES: Assim como a somatria, existem outras
operaes importantes, de grande utilidade, que podem ser obtidas pelas seguintes
equaes usando foldl#
--
-- produto
-- valor especial = 1
--
pro%u1t xs = fol%l (*) 1 xs
--
-- conjuno
-- valor especial = True
--
an% xs = fol%l (&&) *rue xs
--
-- disjuno
-- valor especial = False
--
or xs = fol%l (||) False xs
ExempIo 01: Usando "product para descrever o fatorial de um nmero. Sabemos
que: / fatorial de um n8mero natural n%! 4 igual ao produto de todos os n8meros naturais
de 1 at4 n
--
-- definio de fatorial
--
fat n = pro%u1t 31..n5
...
$ fat "
120
$ fat '
1
$ fat 1
1
ExempIo 02: Podemos usar a disjuno (or) generalizada para definir uma funo
que avalia se em uma dada lista de nmeros pelo menos um deles impar.
111
--
-- pelo menos um impar
--
um@mpar xs = or 3odd x 4 x <- xs5
...
? um@mpar [2,2,2,2,2,2,2,2]
False
? um@mpar [2,2,2,1,2,2,2,2]
True
? um@mpar []
False

14.3. O MENOR ELEMENTO DE UMA LISTA: Estamos interessados em obter uma
funo que associe uma lista xs com o elemento de xs que seja o menor de todos.
Anteriormente j apresentamos uma verso para a funo que descreve o maior
elemento de uma lista, que bastante similar a esta. Na oportunidade exploramos uma
propriedade que o elemento !aior de todos deve satisfazer. No caso do menor elemento,
podemos explorar uma propriedade anloga.
>m uma lista xs1 di$emos que + 4 o menor elemento de xs1 se e somente se a
sublista de xs formada por elementos menores que + 4 7a$ia
--
-- menores descreve os elementos menores que um
-- dado x em uma lista xs
--
menores x xs = [ y | y <- xs, y < x]
-- minimo descreve a sublista de xs dos elementos
-- que no possuem menores que eles em xs
--
minimos xs = [ k | k <- xs, menores k xs == [] ]
--
-- Como eles so todos idnticos podemos tomar o
-- primeiro deles
-- como soluo de nosso problema.
--
menorA' xs = head (menores xs)
Vamos explorar agora o problema a partir da generalizao da operao menor. Em
sua forma bsica, a funo menor associa dois nmeros quaisquer com o menor entre
eles. Precisamos identificar um elemento que no interfira no resultado para fazer o papel
de $alor especial. Para a operao menor podemos observar que este papel pode ser
desempenhado por qualquer um dos elementos da lista, visto que o menor entre dois
valores idnticos o prprio valor. Como pode ser qualquer um, podemos escolher o
primeiro elemento de xs (head).
112
--
-- menor de dois
--
menor x y = if x < y then x else y
--
-- menor da lista
--
menorA xs = fol%l menor (head xs)xs
...
? menorA [5,5,4,4,4,6,6,6,3,3,3,11,1,0]
0
(84 reductions, 157 cells)
? menorA [5]
5
(5 reductions, 13 cells)
? menorA [ ]
ERROR: Unresolved overloading
*** type : Ord a => a
*** translation : menorL []
Podemos observar aqui que a funo menorL parcial pois no se aplica a lista
vazia.
14.4. INSERO ORDENADA E ORDENAO DE UMA LISTA: A ordenao de dados
uma das operaes mais realizadas em computao. Em todos os computadores do
mundo, faz-se uso intensivo dela. Este assunto muito especial e por isso mesmo
profundamente estudado. Cabe-nos aqui fazer uma breve passagem pelo assunto, sem,
contudo nos aprofundarmos nas questes de eficincia, que central no seu estudo.
Ser que podemos usar o conceito de generalizao de uma operao para
descrever a ordenao de uma lista? Que operao seria essa?
14.4.1. INSERO EM LISTA ORDENADA - Vamos comear discutindo outra
questo mais simples: dada uma lista, com seus elementos j dispostos em ordem no
decrescente, como descrever uma lista na mesma ordem, acrescida de um elemento
tambm fornecido?
Podemos observar que se a lista xs est em ordem no decrescente, com respeito ao
elemento x (dado), podemos descrev-la atravs de dois segmentos:
xs ( S!enores que x' ++ S!aiores ou i,uais a x'
Para acrescentar x a xs, basta concatenar x entre os dois segmentos, obtendo a nova
lista ys, assim:
s ( S!enores que x e! xs' ++ [x] ++ S!aiores ou i,uais a x e! xs'
113
-- insero ordenada
--
--
insor% xs x = ta8eBhile (< x) xs
++ [x]
++ %ropBhile (< x) xs
...
Main> insord [] 10
[10]
(27 reductions, 49 cells)
Main> insord [10] 20
[10,20]
(54 reductions, 84 cells)
Main> insord [10,20] 30
[10,20,30]
(79 reductions, 119 cells)
Main> insord [10,20,30] 5
[5,10,20,30]
(71 reductions, 110 cells)
Main> insord [5,10,20,30] 25
[5,10,20,25,30]
(126 reductions, 183 cells)
14.4.2. Ordenao - A APLICAO SUCESSIVA DE INSORD , CONFORME
ILUSTRADA ACIMA, NOS D UMA PISTA PARA NOSSA GENERALIZAO.
PODEMOS PEGAR CADA ELEMENTO DA LISTA A SER ORDENADA E INSERI-LO EM
ORDEM EM OUTRA LISTA QUE SER PAULATINAMENTE CONSTRUDA, J
ORDENADA. VAMOS SEGUIR O EXEMPLO ACIMA, ONDE DESEJAMOS ORDENAR A
LISTA [10,20,30,5,25]:
Iista parciaI
novo
eIemento
reduo
[] 10 [10]
[10] 20 [10,20]
[10,20] 30 [10,20,30]
[10,20,30] 5 [5, 10, 20, 30]
[5, 10, 20, 30] 25 [5, 10, 20, 25, 30]
O ponto de partida, neste caso, a lista vazia. Vamos tomar ento a lista vazia como
o valor especial. Vejamos como fica ento nossa definio para ordenao de listas.
114
-- ordenao
--
or%ena xs = fol%l insord [] xs
...
Main> or%ena [10,20,30,5,25]
[5,10,20,25,30]
(220 reductions, 344 cells)
Main> or%ena [1..10]
[1,2,3,4,5,6,7,8,9,10]
(1055 reductions, 1505 cells)
Main> or%ena [10,9..1]
[1,2,3,4,5,6,7,8,9,10]
(448 reductions, 712 cells)

14.5. INVERSO DE UMA LISTA: Dada uma lista xs, desejamos descrever a lista formada
pelos elementos de xs tomados em ordem inversa.
Para resolver o problema precisamos inventar uma funo bsica passvel de
generalizao.
Vamos comear descrevendo a funo insAntes.
--
-- Insere um elemento antes do primeiro elemento
-- de uma dada lista. Funo similar ao operador
-- (:) exceto pela ordem invertida dos parmetros
--
insCntes xs x = x : xs
...
Main> insCntes [1..5] 0
[0,1,2,3,4,5]
(171 reductions, 255 cells)
Main> insCntes [] 0
[0]
(22 reductions, 29 cells)
Tentemos agora a generalizao. A inteno incluir cada elemento da lista xs que
desejamos inverter, antes do primeiro elemento de uma lista que iremos construindo
gradativamente. O $alor especial ser a lista vazia. Vejamos um exemplo onde
inverteremos a lista [0, 1, 2, 3, 4]
Iista parciaI
novo
eIemento
reduo
[] 0 [0]
[0] 1 [1, 0]
[1, 0] 2 [2, 1, 0]
[2, 1, 0] 3 [3, 2, 1, 0]
[3, 2, 1, 0] 4 [4, 3, 2, 1, 0]
115
Vamos ento usar o operador foldl para construir a generalizao desejada:
-- inversao
--
in+erte xs = fol%l insAntes [] xs
...
Main> in+erte [0..4]
[4,3,2,1,0]
(172 reductions, 259 cells)
Main> in+erte [4,3..4]
[4]
(74 reductions, 110 cells)
...
Main> re+erse [4,3..4]
[4]
(74 reductions, 111 cells)
Main> re+erse [0..4]
[4,3,2,1,0]
(171 reductions, 257 cells)
Observe a similaridade entre o desempenho da funo reverse, pr-definida, com o
desempenho da inverte que acabamos de definir.
14.6. INTERCALAO DE LISTAS: Dadas duas lista xs e ys, ambas em ordem no
decrescente, desejamos descrever uma nova lista em ordem no decrescente, formada
por todos os elementos das duas listas.
Um processo bastante conhecido, chamado de +alance line, consiste em ir
transferindo para a nova lista, os elementos de uma das listas de entrada, enquanto estes
forem menores que os da outra. Quando a condio no mais satisfeita, fazemos o
mesmo para a outra lista.
Por exemplo, vamos intercalar as listas [2, 4, 6, 8] e [1, 3, 5]. Vejamos o desenrolar do
processo.
Iista parciaI
Andamento
em xs
Andamento
em ys
Reduo
[] [2, 4, 6, 8] [1, 3, 5] [1]
[1] [2, 4, 6, 8] [3, 5] [1, 2]
[1, 2] [ 4, 6, 8] [3, 5] [1, 2, 3]
[1, 2, 3] [ 4, 6, 8] [5] [1, 2, 3, 4]
[1, 2, 3, 4] [6, 8] [5] [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5] [6, 8] [] [1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6] [ 8] [] [1, 2, 3, 4, 5, 6, 8]
[1, 2, 3, 4, 5, 6, 8] [] []
Vamos precisar aqui de uma bela engenharia para a construo da funo a
generalizar. Desta vez, nossa entrada formada por duas listas e como sabemos o
116
operador foIdI, a cada vez, processa um elemento de uma determinada lista. sto nos leva
a ter que inventar tambm a lista a ser processada.
A funo bsica pode ser inventada a partir da descrio de um passo do processo
que denominamos de +alance line. Em cada passo temos como entrada uma lista
parcialmente construda e duas listas parcialmente processadas. Como sada teremos
mais um passo de construo da lista resultante e o andamento no processamento de uma
das listas. Na lista em construo devemos inserir o menor entre os cabeas (head) das
duas listas. Aquela que tiver o menor cabea dar origem a uma nova lista, da qual foi
excludo o primeiro elemento, ou seja, ser idntica ao resto (tail) da lista escolhida.

117
--
-- Descrio de um passo do Balance Line.
-- 1) Quando uma das duas listas for vazia a
-- outras diretamente concatenada no final
-- da lista em construo.
--
passoDA (xs,ys,zs) = if (ys == [])
then ([],[],zs++xs)
else if (xs == [])
then ([],[],zs++ys)
else if (head xs <= head ys)
then (tail xs,ys,zs++[head xs])
else (xs, tail ys,zs++[head ys])
...
... aplicao sucessiva da funo passoDA intercalao
... das listas acima propostas
...
Main> passoDA ([2,4,6,8],[1,3,5],[])
([2,4,6,8],[3,5],[1])
(121 reductions, 219 cells)
Main> passoDA ([2,4,6,8],[3,5],[1])
([4,6,8],[3,5],[1,2])
(122 reductions, 222 cells)
Main> passoDA ([4,6,8],[3,5],[1,2])
([4,6,8],[5],[1,2,3])
(123 reductions, 225 cells)
Main> passoDA ([4,6,8],[5],[1,2,3])
([6,8],[5],[1,2,3,4])
(124 reductions, 228 cells)
Main> passoDA ([6,8],[5],[1,2,3,4])
([6,8],[],[1,2,3,4,5])
(128 reductions, 239 cells)
Main> passoDA ([6,8],[],[1,2,3,4,5])
([],[],[1,2,3,4,5,6,8])
(116 reductions, 223 cells)
...
Main> passoDA ([1..5],[],[])
([],[],[1,2,3,4,5])
(190 reductions, 329 cells)
Main> passoDA ([],[1..5],[])
([],[],[1,2,3,4,5])
(193 reductions, 339 cells)
Main> passoDA ([1..3],[4..5],[])
([2,3],[4,5],[1])
(219 reductions, 371 cells)
A generalizao, de forma que possamos aplicar a funo gradativamente, de tal
forma que todo o processo se complete, requer a inveno de uma lista sobre a qual
ocorra a repetio. O nmero de aplicaes sucessivas ser no mximo igual soma dos
comprimentos das listas a serem intercaladas. Podemos ento definir a aplicao sobre a
lista dos nmeros de 1 at a soma dos tamanhos.
118
--
-- Funo para Intercalar duas listas ordenadas
-- 1) a funo passoBL repetidamente aplicada, sobre
-- o resultado obtido no passo anterior;
-- 2) a funo passoBL binria, como exigido por foldl;
-- 3) a aplicao sucessiva controlada pelo comprimento
-- da lista resultante;
-- 4) o resultado final obtido pela seleo do terceiro
-- elemento da tripla atravs da primitiva "thd3"
--
?aAine xs ys = thrd3 (baLine3 xs ys)
--
thr%3 (x,y,z) = z
--
?aAine3 xs ys = foldl passoBL (xs,ys,[]) [1..tr]
where
tr = (length xs)+(length ys)
--
-- Descrio de um passo do Balance Line.
-- 1) Quando uma das duas listas for vazia a
-- outras diretamente concatenada no final
-- da lista em construo.
-- 2) O parmetro k apenas para estabelecer o tipo
-- binrio exigido por foldl
--
passoDA (xs,ys,zs) k = if (ys == [])
then ([],[],zs++xs)
else if (xs == [])
then ([],[],zs++ys)
else if (head xs <= head ys)
then (tail xs,ys,zs++[head xs])
else (xs, tail ys,zs++[head ys])
...
Main> thr%3 (10,20,30)
30
(11 reductions, 12 cells)
Main> ?aAine3 [1..3] [4..6]
([],[],[1,2,3,4,5,6])
(514 reductions, 896 cells)
Main> ?aAine [1..3] [4..6]
[1,2,3,4,5,6]
(485 reductions, 784 cells)
Main> ?aAine [1..5] [3..7]
[1,2,3,3,4,4,5,5,6,7]
(807 reductions, 1326 cells)
Main> ?aAine [2, 4, 6, 8] [1, 3, 5]
[1,2,3,4,5,6,8]
(425 reductions, 696 cells)
Exerccios: Use o paradigma aplicativo para resolver os problemas abaixo:
1.Dadas duas strings xs e ys, verificar se xs sublista de ys.
2.Definir a funo tWhile, que tenha o mesmo comportamento que a funo takeWhile.
3.Definir a funo dWhile, que tenha o mesmo comportamento que a funo dropWhile.
4.Verificar se uma string um palndrome (a string a mesma quando lida da esquerda
para a direita ou da direita para a esquerda).
119
15. Processamento de Cadeias de Caracteres - primeiros passos
15.1. INTRODUO: Alm de nmeros, nosso mundo povoado por textos. Cada vez
mais se torna presente o uso de computadores para nos auxiliar na tarefa de armazenar,
recuperar e processar documentos. Neste captulo estamos interessados em fazer uma
breve introduo ao uso de computadores nessas tarefas.
O ponto de partida o tipo caracter (char), que nos permite representar textos na
memria (principal e secundria) dos computadores. Veremos tambm como agrup-los
para compor palavras, frases e por fim documentos.
15.2. O TIPO CHAR: O tipo char formado por um conjunto de smbolos. Outro nome
usado para esta coleo alfabeto, ou seja, o conjunto de tomos que serviro de base
para a construo de cadeias complexas, inclusive os textos usuais. Entre os smbolos
citados podemos destacar trs agrupamentos relevantes, tais como:
1. As letras maisculas do alfabeto;
2. As letras minsculas do alfabeto;
3. Os algarismos arbicos;
Estes trs agrupamentos gozam de uma propriedade muito importante. Dentro deles
os smbolos possuem uma relao de ordem, de tal forma que podemos usar a noo
usual de ordenao para letras e algarismos.
Alm destes, podemos citar ainda os sinais de pontuao e alguns smbolos com
funes especiais, como, por exemplo, indicador de final de linha de texto. Os smbolos
so sempre apresentados em HUGS entre aspas simples, para que possam ser
diferenciados dos nomes de parmetros, funes e outros. Por exemplo, a letra a deve ser
denotada por TaU #
A definio a seguir ajuda a esclarecer esta necessidade.
f a = (a, 'a')
Aqui usamos a letra "a trs vezes. A primeira, da esquerda para direita, nomeia um
parmetro da funo "f. Na segunda ocorrncia, utilizamos o parmetro da funo para se
constituir do primeiro elemento de uma tupla. J a terceira ocorrncia se refere constante
"a.
Vejamos as respostas do sistema para diferentes usos da funo f
120
1 Eain> f 3
(3,'a')
! Eain> f 5
(5,'a')
3 Eain> f a
ERROR - Undefined variable "a"
4 Eain> f 'a'
('a','a')
" Eain> f 'aa'
ERROR - Improperly terminated character constant
6 Eain> f 'b'
('b','a')
# Eain> f a where a='a'
('a','a')
Nas situaes 1, 2, e 6, o parmetro a instanciado para os valores 3, 5 e 'b' , resultando
nos pares (3, 'a'), (5,'a') e (b, 'a'). Na situao 4, o parmetro a instanciado para a
constante 'a', produzindo o par ('a', 'a'). Na situao 3, o uso de a est incorreto, pois como
no est entre as aspas simples, interpretado como um parmetro, que no est
instanciado quando deveria estar. Na situao 7, ao contrrio da situao 3, o valor de a
instanciado atravs da clusula where e a situao fica similar situao 4.
A coleo total dos smbolos de nosso alfabeto forma uma seqncia de tal forma
que podemos fazer o mapeamento entre a subseqncia de nmeros naturais, de zero (0)
a 255 e a seqncia de smbolos.
Duas funes bsicas permitem que se faa a converso entre as duas seqncias. Elas
podem ser encontradas em uma biblioteca de funes diferente de Prelude.hs. Essa
biblioteca se chama Data.Char. Para usar essas funes no seu interpretador HUGS,
preciso executar o comando :I Data.Char no interpretador:
1. A funo c7r associa um nmero natural no intervalo [0,255] com o caracter
correspondente. Por exemplo, c7r 64 = '@' e c7r 38 = '&'.
2. A funo ord faz o mapeamento inverso, ou seja, associa um smbolo com o
nmero natural correspondente. Por exemplo, ord '?' = 63 e ord '%' = 37.
A tabela a seguir apresenta alguns dos agrupamentos importantes.
121
AIgarismos
Letras
MaiscuIas
Letras
MinscuIas



,' a
,+ b
,, c
1-- d
1-1 e
1-( '
1-3 (
1-( )
1-. i
1-$ *
1-' +
1-+ l
1-, ,
11- n
111 o
11( "
113 -
114 r
11. s
11$ t
11' u
11+ v
11, .
1(- x
1(1 /
1(( 0
1(3 1
1(4 2
1(. 3
1($ 4
Alm das operaes ord e chr, podemos contar com os operadores relacionais que
foram apresentados no Captulo 6. Da mesma forma que existem os operadores para
122
3( 5 5
33 6
34 7
3. 8
3$ 9
3' :
3+ ;
3, <
4- (
41 )
4( =
43 +
44 ,
4. >
4$ ?
4' @
4+ A
4, $
.- %
.1 &
.( B
.3 C
.4 D
.. E
.$ F
.' G
.+ :
., H
$- I
$1 =
$( J
$3 K
$4 L
$. M
$$ N
$' C
$+ D
$, #
'- F
'1 O
'( P
'3 Q
'4 R
'. S
'$ T
'' U
'+ N
', V
+- W
+1 X
+( Y
+3 Z
+4 T
+. [
+$ \
+' ]
++ ^
+, _
,- `
,1 [
,( /
,3 ]
,4 a
,. 0
,$ 1
comparao de nmeros, existe os operadores relacionais que comparam dois smbolos,
como no exemplo:
Prelude> 'c' > 'h'
False
O significado de uma operao relacional sobre characteres determinado com base
na ordem destes com respeito tabela apresentada para codificao desses smbolos.
Assim, podemos dizer que:
Se x e y so do tipo caractere, x > y se e somente se ord x > ord y
Podemos agora construir algumas definies interessantes, conforme se apresenta
nos quadros a seguir:
--
-- +erifi1a se um %a%o sFm?olo G letra
--
letra x = (maiuscula x) || (minuscula x)
--
maiuscula x = pertence x ('A','Z')
minuscula x = pertence x ('a','z')
pertence x (a,b) = (x >= a) && (x <= b)
--
-- verifica se um smbolo um algarismo
--
algarismo x = pertence x ('0','9')
--
-- Associa uma letra minuscula com a sua
-- correspondente maiuscula e mantm o
-- smbolo fornecido nos demais casos
--
caps x = if minuscula x
then chr (ord x - 32)
else x
--
-- Determina a posio relativa de uma letra
-- dentro do alfabeto, onde as maisculas e
-- minsculas possuem a mesma posio.
-- Outros smbolos devem ser associados ao
-- valor 0 (zero)
--
ordAlfa x = if letra x
then ord (caps x) - 64
else 0
Eis mais alguns exemplos de funes com o tipo char.
123
--
-- verifica se um smbolo uma letra vogal
--
+ogal x = letra x && ocorre (caps x) vogais
where
vogais = ['A','E','I','O','U']
--
o1orre x xs = or [x == y | y<- xs]
--
-- verifica se um smbolo uma letra
-- consoante
--
1onsoante x = letra x && (not (vogal x))
--
--
-- Descreve uma lista de pares onde o primeiro termo
-- um nmero entre 0 e 255 e o segundo o caracter
-- correspondente. O intervalo desejado informado
-- por um par de valores no intervalo 0 a 255.
--
ta?Hr%Ihr (i,f) = [(x, chr x) | x <- [i..f]]
Vejamos alguns exemplos de uso das definies acima apresentadas:
Main> ta?Hr%Ihr (65,70)
[(65,'A'),(66,'B'),(67,'C'),(68,'D'),(69,'E'),(70,'F')]
(357 reductions, 604 cells)
Main> ta?Hr%Ihr (97,102)
[(97,'a'),(98,'b'),(99,'c'),(100,'d'),(101,'e'),(102,'f')]
(357 reductions, 607 cells)
Main> ta?Hr%Ihr (45,50)
[(45,'-'),(46,'.'),(47,'/'),(48,'0'),(49,'1'),(50,'2')]
(357 reductions, 604 cells)
15.3. O TIPO STRING: Podemos agrupar tomos do tipo caracter (char) para formar o que
denominamos de cadeia de caracteres, usualmente chamadas de "palavra". O mecanismo
para agregar o construtor da lista. Podemos por exemplo, escrever em HUGS a lista
['c','i','d','a','n','i','a'] para representar a palavra cidadania#
Assim procedendo podemos escrever qualquer texto, uma vez que um texto no
nada mais nada menos que uma longa cadeia de smbolos envolvendo letras e sinais de
pontuao. A separao de palavras obtida pelo uso de um caracter especial,
denominado de espa3o, que tem representao interna igual a 32. Por exemplo, para
representar a expresso "Vamos nessa!", usamos a lista:
['V','a','m','o','s',' ','n','e','s','s','a','!'].
124
Uma boa notcia que o HUGS nos proporciona uma maneira mais amistosa para
tratar com lista de caracteres. Em HUGS podemos representar uma lista de caracteres,
envolvendo a cadeia por aspas duplas, o que por certo, alm de mais elegante e legvel,
no poupa trabalho. Por exemplo, a cadeia acima representada por ser tambm escrita na
seguinte forma:
"Vamos nessa!"
uma lista de caracteres o HUGS associa um tipo sinnimo, denominado strin,.
Assim, as duas representaes acima so idnticas, conforme podemos observar na
avaliao abaixo:

Prelude> "Vamos nessa!" == ['V','a','m','o','s',' ','n','e','s','s','a','!']
True
(64 reductions, 102 cells)
Um bom lembrete que, cadeias de caracteres so definidas como listas, e como
tais, podemos usar sobre elas todas as operaes que sabemos at agora sobre listas.
Por exemplo, podemos construir uma funo para contar a quantidade de vogais
existente em uma cadeia.

contaVogais xs = length vogais
where
vogais = [x | x <-xs, vogal x]
...
Main> contaVogais "Vamos nessa!"
4
(966 reductions, 1383 cells)

15.4. FUNES BSICAS PARA O TIPO STRING: Uma cadeia de caracteres, por ser
uma lista, herda todas as operaes que j apresentamos para as listas. Alm dessas,
podemos contar ainda com algumas operaes que apresentamos a seguir:
words xs - Associa uma cadeia de caracteres com a lista de pala7ras nela contida.
Entende-se por pala7ra um agrupamento de smbolos diferentes do smbolo espa3o (J J)#

Prelude> or%s "Se temos que aprender a fazer, vamos
aprender fazendo!"
["Se","temos","que","aprender","a","fazer,",
"vamos","aprender","fazendo!"]
(2013 reductions, 3038 cells)
Podemos observar que os smbolos usuais de separao (por exemplo, "," e "!" so
considerados como parte das pala7ras. Vamos agora construir uma funo que considere
os smbolos usuais de separao, alm do espao.
125
--
-- A funo pala+ras
--
pala+ras xs = [ takeWhile letra x | x <- words xs]
--
--
--
...
Main> pala+ras "Se temos que aprender a fazer, vamos aprender fazendo!"
["Se","temos","que","aprender","a","fazer","vamos","aprender","fazendo"]
(3869 reductions, 5444 cells)
Main> pala+ras "jose123 maria456 joana!!!"
["jose","maria","joana"]
(1445 reductions, 2081 cells)
Main> or%s "jose123 maria456 joana!!!"
["jose123","maria456","joana!!!"]
(951 reductions, 1423 cells)

De fato, a funo paIavras trata a questo proposta: abandonar os smbolos de
pontuao. Acontece que ela abandona muito mais que isso, como podemos ver no
exemplo, onde a cadeia "jose123" perde o seu sufixo numrico, tornando-se apenas "jose".
Vamos construir uma nova funo ento onde isso possa ser resgatado.

--
-- A funo pala+ras1
--
pala+ras1 xs = [ takeWhile alfa x | x <- words xs]
where alfa x = letra x || algarismo x
--
--
--
...
Main> pala+ras1 "x123 y456 aux!!!"
["x123","y456","aux"]
Bom, parece que agora temos uma soluo adequada.
Exerccios
1. Verificar se uma letra vogal.
2. Verificar se uma letra consoante.
3. Gerar a lista de pares onde o primeiro termo um nmero entre 0 e 255 e o
segundo termo o caracter correspondente pela tabela ASC. O intervalo de
valores desejados informado por um par de valores entre 0 e 255.
4. Dadas duas strings xs e ys, verificar se xs prefixo de ys.
5. Dadas duas strings xs e ys, verificar se xs sufixo de ys.
6. Dadas duas strings xs e ys, verificar se xs sublista de ys.
126
16. O PARADIGMA RECURSIVO
127
16.1. INTRODUO: Como j falamos anteriormente, existem vrias maneiras de definir
um conceito. A essas maneiras convencionamos chamar de paradigmas. Aqui trataremos
de mais um destes, o paradigma recursivo. Dizer que trataremos de mais um simplificar
as coisas, na verdade este paradigma um dos mais ricos e importantes para a descrio
de computaes. O domnio deste paradigma de fundamental importncia para todo
aquele que deseja ser um expert em Programao de Computadores enquanto cincia e
tecnologia.
De uma maneira simplificada podemos dizer que o ncleo deste paradigma consiste
em descrever um conceito de forma recursiva. sto equivale a dizer que definiremos um
conceito usando o prprio conceito. Apesar de disto parecer muito intrigante, no se
assuste, aos poucos, quando esboarmos melhor a idia ela se mostrar precisa, simples
e poderosa.
Vamos pensar num conceito bem corriqueiro. Que tal definirmos o conceito escada.
Como podemos descrever escada usando a prpria escada? A resposta bem
simples:
Q!a escada i,ual a u! de,rau se,uido de u!a escada (Figura 15.1).
Fcil no ? Ser que isto basta? Onde est o truque? Parece que estamos andando
em crculo, no mesmo? Para entender melhor vamos discutir a seguir alguns elementos
necessrios para a utilizao correta da recurso na definio de novas funes.
16.2. DESCRIO RECURSIVA DE UM CONCEITO FAMILIAR: Antes de avanar em
nossa discusso vamos apresentar mais um exemplo. Desta vez usaremos um que
bastante familiar para alunos de cincias exatas. Estamos falando da descrio do fatorial
de um nmero. J vimos neste curso uma forma de descrever este conceito dentro do
HUGS quando estudamos o paradigma aplicativo. Na oportunidade usamos a seguinte
descrio:
/ fatorial de um n8mero natural n % ! 4 igual
ao produto de todos os n8meros naturais de 1 at4 n
128
degrau
escada
escada
Figura 15.1 Uma escada
Ou ainda em notao mais formal:
n 6 = $ x % x & x ??? x n
Em HUGS, como j vimos, teremos a seguinte definio:
--
-- definio (aplicativa) de fatorial
--
fat n = pro%u1t 31..n5
...
$ fat "
120
$ fat '
1
$ fat 1
1
H uma outra forma de definir, tambm familiar aos alunos do primeiro ano
universitrio:
/ Aatorial de um n8mero natural n 4 igual ao produto deste n8mero pelo fatorial de seu
antecessor
Novamente, sendo mais formal, podemos escrever:
n 6 = n x (n > $) 6
E em HUGS, como ficaria? Que tal a definio a seguir?
--
-- definio recursiva de fatorial
--
fat n = n J fat &n - 1)
Vamos exercitar a definio:
Main> fat "
(23967 reductions, 47955 cells)
:RRHR: Iontrol sta18 o+erflo
Bom, parece que houve um pequeno problema com nossa definio. A avaliao de
fat 5 produziu uma situao de erro. Vamos deixar para entender este erro melhor para
depois. Por enquanto j podemos adiantar que ele foi provocado por um pequeno
esquecimento de nossa parte.
129
Na verdade a nossa definio recursiva para fatorial estava incompleta. Esta que
exibimos s se aplica aos naturais maiores que zero. A definio do fatorial de zero no
recursiva, ela independente:
M fatorial de 1ero i,ual a %#
Temos ento duas definies para fatorial e precisamos integr-las. Vejamos uma
tentativa:
/ Aatorial de um n8mero natural n 4)
1. igual a 1 se n=!9
2 igual ao produto deste n8mero pelo fatorial de
seu antecessor1 se n % !
Vamos ver como essa integrao pode ser feita em HUGS. Podemos de imediato
observar que trata-se de uma definio condicional e logo nos vem a lembrana de que
nossa linguagem possui um mecanismo, as expresses condicionais.
--
-- definio recursiva de fatorial
-- (corrigida)
--
fat n = if n==0
then 1
else n * fat (n - 1)
Vamos submeter algumas situaes para o HUGS:
Main> fat "
120
(79 reductions, 124 cells)
Main> fat !'
2432902008176640000
(258 reductions, 466 cells)
Main> fat '
1
(18 reductions, 18 cells)
Pelo visto agora deu tudo certo.
16.3. ELEMENTOS DE UMA DESCRIO RECURSIVA: Em uma descrio
recursiva devemos ter em conta certo elementos importantes. fundamental que todos
eles sejam contemplados para que nossas descries estejam corretas. O exemplo
anteriormente apresentado suficiente para ilustrar todos eles. Vamos ento discuti-los:
Definio geraI : Toda definio recursiva tem duas partes, uma delas se aplica a um
valor qualquer do domnio do problema, denominamos de geral. Esta tem uma
caracterstica muito importante, o conceito que est sendo definido deve ser utilizado. Por
exemplo, para definir fatorial de n, usamos o fatorial do antecessor de n. Observe aqui,
entretanto que o mesmo conceito foi utilizado, mas no para o mesmo valor. Aplicamos o
conceito a um valor mais simples, neste caso o antecessor de n.
130
Definio independente : A outra parte da definio destinada ao tratamento de
um valor to simples que a sua definio possa ser dada de forma independente. Este
elemento tambm conhecido como base da recurso. No caso do fatorial, o valor
considerado o zero.
Obteno de vaIores mais simpIes : Para aplicar o conceito a um valor mais
simples precisamos de uma funo que faa este papel. No caso do fatorial, usamos a
subtrao de n por 1, obtendo assim o antecessor de n. Em cada caso, dependendo do
domnio do problema e do problema em si, precisaremos encontrar a funo apropriada.
Funo auxiIiar : Na definio geral, para obter um valor usando o valor considerado
e o valor definido recursivamente, em geral faz-se necessrio o uso de uma funo
auxiliar. Algumas vezes esta funo pode ser originada a partir de um conceito aplicvel a
dois elementos e que desejamos estender aos elementos de uma lista. Um exemplo o
caso da somatria dos elementos de uma lista, como veremos adiante. No caso do fatorial
esta funo a multiplicao.
Garantia de atingir o vaIor independente : fundamental que a aplicao
sucessiva da funo que obtm valores mais simples garanta a determinao do valor
mais simples. Este valor tambm denominado de base da recurso. Por exemplo, no
caso do fatorial, sabemos que aplicando a subtrao sucessivas vezes produziremos a
seqncia:
n, (n-1), (n-2), ... 0
/sta condi34o funda!ental para ,arantir que ao
a$aliar!os u!a express4o atin,ire!os a +ase da recurs4o#
Voltemos definio do fatorial para destacarmos os elementos acima citados, como
podemos observar no quadro esquemtico a seguir:
131
16.4. AVALIANDO EXPRESSES: A esta altura dos acontecimentos a curiosidade sobre
como avaliar expresses usando conceitos definidos recursivamente j deve estar
bastante aguada. No vamos, portanto retardar mais essa discusso. Apresentamos a
seguir um modelo bastante simples para que possamos entender como avaliar expresses
que usam conceitos definidos recursivamente. Novamente no precisaremos entender do
funcionamento interno de um computador nem da maneira como uma determinada
implementao de HUGS foi realizada. Basta-nos o conceito de reduo que j
apresentamos anteriormente.
Relembremos o conceito de reduo. O avaliador deve realizar uma seqncia de
passos substituindo uma expresso por sua definio, at que se atinja as definies
primitivas e os valores possam ser computados diretamente.
Vamos aplicar ento este processo para realizar a avaliao da expresso fat 5
passo Reduo Justificativa
0fat 5 expresso proposta
15 * fat 4
substituindo fat por sua definio
geral
25*(4 * fat 3) dem
35*(4* (3 * fat 2)) dem
45*(4*(3*(2 * fat 1))) dem
55*(4*(3*(2*(1 * fat 0) dem
65*(4*(3*(2*(1 * 1)))) usando a definio especfica
75*(4*(3*(2*1))) usando a primitiva de multiplicao
85*(4*(3*2) dem
95*(4*6) dem
105 * 24 dem
11120 dem
132
Surpreso(a)? Simples, no? assim mesmo, bem simples. A cada passo vamos
substituindo uma expresso por outra at que nada mais possa ser substitudo. O
resultado surgir naturalmente. Mais tarde voltaremos ao assunto.
16.5. RECURSO EM LISTAS: A esta altura deste curso j estamos certos que o uso de
lista indispensvel para escrever programas interessantes. Em vista disso, nada mais
bvio que perguntar sobre o uso de recurso em listas. Veremos que o uso de definies
recursivas em listas produz descries simples, precisas e elegantes.
J est na hora de alertar que os valores sobre os quais aplicamos os conceitos que
queremos definir recursivamente possuem uma caracterstica importantssima, eles em si
so recursivos.
Por exemplo, qualquer valor pertencente aos naturais pode ser descrito a partir da
existncia do zero e da funo sucessor (suc). Vejamos como podemos obter o valor 5:
5 ( suc(suc(suc(suc(suc -)))))
As listas so valores recursivos. Podemos descrever uma lista da seguinte maneira:
Uma lista :
1. a lista vazia;
2. um elemento seguido de uma
lista
Esta natureza recursiva das listas nos oferece uma oportunidade para, com certa
facilidade, escrever definies recursivas. A tcnica consiste basicamente em:
1. Obter a definio geral: isto consiste em identificar uma operao
binria simples que possa ser aplicada a dois valores. O primeiro deles
o primeiro (head) da lista e o outro um valor obtido pela aplicao
do conceito em definio ao resto (taiI) da lista;
2. Obter a definio independente, que se aplicar base da recurso.
Esta, em geral, a lista $a1ia;
3. Garantir que a aplicao sucessiva do taiI levar base da recurso.
Na Figura 15.2 ilustramos o processo recursivo de obter listas cada vez menores,
atravs da aplicao da funo taiI. Ao final do processo obteremos a lista vazia ([ ]).
133
ExempIo 01 - Descrever o somatrio dos elementos de uma lista.
SoIuo - Podemos pensar da seguinte maneira: o somatrio dos elementos de uma
lista igual soma do primeiro elemento da lista como o somatrio do resto da lista. Alm
disso, o somatrio dos elementos de uma lista vazia igual a zero.
Vejamos ento a codificao:
--
-- definio recursiva da somatria dos
-- elementos de uma lista
--
somat ,s = if null ,s
then '
else hea% ,s 9 somat &tail ,s)
[x
o
, x
1
, x
2
, x
3
, x
4
... x
n-1
]
x
o
[x
1
, x
2
, x
3
, x
4
... x
n-1
]
taiI
x
1
[x
2
, x
3
, x
4
... x
n-1
]
x
2
[x
3
, x
4
... x
n-1
]
x
3
[x
4
... x
n-1
]
x
4
[... x
n-1
]
x
n-1
[ ]

...
Figura 15.2 - componentes recursivos de uma Iista
head
134
x
o
+ somat [x
1
, x
2
, x
3
, x
4
... x
n-1
]
X
0
+ x
1
+ somat [x
2
, x
3
, x
4
... x
n-1
]
...
X
0
+ x
1
+ x
2
+ somat [x
3
, x
4
... x
n-1
]
X
0
+ x
1
+ x
2
+ x
3
+ somat [x
4
... x
n-1
]
X
0
+ x
1
+ x
2
+ x
3
+ somat [x
4
... x
n-1
]
X
0
+ x
1
+ x
2
+ x
3
+ x
4
+ somat [... x
n-1
]
X
0
+ x
1
+ x
2
+ x
3
+ x
4
+ ... + x
n-1
+ somat [ ]
somat [x
o
, x
1
, x
2
, x
3
, x
4
... x
n-1
]
Figura 15.2 desenvolvimento da computao de
somatrio dos elementos de uma lista
X
0
+ x
1
+ x
2
+ x
3
+ x
4
+ ... + x
n-1
+ 0
A seguir alguns exemplos de uso:
Main> somat [4,5,2,7,9]
27
(52 reductions, 60 cells)
Main> somat [1..10]
55
(275 reductions, 421 cells)
Main> somat [1000,9999..1]
0
(45 reductions, 68 cells)
Main> somat [1000,999..1]
500500
(18051 reductions, 25121 cells)
ExempIo 02 - Descrever a funo que determina o elemento de valor mximo uma
lista de nmeros.
SoIuo: O mximo de uma lista o maior entre o primeiro elemento da lista e o
mximo aplicado ao resto da lista. Uma lista que tem apenas um elemento tem como valor
mximo o prprio elemento (Figura 15.3).
A definio recursiva apresentada a seguir:
--
-- definio recursiva do mximo de uma lista
--
ma,imo ,s = if null &tail ,s)
then hea% ,s
else maior &hea% ,s) &ma,imo &tail ,s))
--
maior , 7 = if , > 7 then , else 7
E vamos acompanhar agora algumas submisses:
Main> ma,imo 34(6(#(.0(3!(4"(0.(6"(315
98
(126 reductions, 150 cells)
Main> ma,imo &31..1'''59931"''(14''..15)
135
maximo [x
o
, x
1
, x
2
, x
3
, x
4
... x
n-1
]
maior( x
o
, maximo [x
1
, x
2
, x
3
, x
4
... x
n-1
] )
maior( x
o
, maior(x
1
, maximo [x
2
, x
3
, x
4
... x
n-1
])) ))
maior( x
o
, maior(x
1
, maior(x
2,
maximo [x
3
, x
4
... x
n-1
] )))
maior( x
o
, maior(x
1
, maior(x
2,
maior(x
3,
maximo [x
4
... x
n-1
] ))))
maior( x
o
, maior(x
1
, maior(x
2,
maior(x
3,
maior(x
4
, ... maximo[x
n-2
, x
n-1
])))))
maior( x
o
, maior(x
1
, maior(x
2,
maior(x
3,
maior(x
4
, ... maior(x
n-2 ,
maximo[ x
n-1
])))))
maior( x
o
, maior(x
1
, maior(x
2,
maior(x
3,
maior(x
4
, ... maior(x
n-2 ,
x
n-1
))))))
Figura 15.3 desenvolvimento da computao do elemento mximo de
uma lista
1500
(31419 reductions, 44567 cells)
Main> ma,imo 31''(&1'' - 8) .. 15 here 8 = .'
100
(91 reductions, 125 cells)
E agora uma surpresa.
Main> ma,imo 3 5
ERROR: Unresolved overloading
*** Type : Ord a => a
*** Expression : maximo []
Voc consegue explicar?
ExempIo 03 - Descrever a funo que verifica se um dado valor ocorre em uma lista
tambm dada.
SoIuo : Podemos pensar da seguinte maneira: Um dado elemento k ocorre em
uma lista se ele igual ao primeiro elemento da lista ou se ele ocorre no resto da lista. Em
uma lista vazia no ocorrem elementos quaisquer (Figura 15.4).
Vejamos ento a codificao:
--
-- descreve a ocorrncia de dado k em uma lista xs
--
o1orre 8 ,s = if null ,s
then False
else &8==hea%&,s)) 44 o1orre 8 &tail ,s)
E algumas submisses:
136
ocorre k [x
o
, x
1
, x
2
, x
3
, x
4
... x
n-1
]
k = x
o
| ocorre k [x
1
, x
2
, x
3
, x
4
... x
n-1
]
k = x
o
| (k = x
1
| ocorre k [x
2
, x
3
, x
4
... x
n-1
])
k = x
o
| (k = x
1
| ( k = x
2
| ocorre k [x
3
, x
4
... x
n-1
]))
k = x
o
| (k = x
1
| ( k = x
2
| (k = x
3
| ocorre k [x
4
... x
n-1
])))
k = x
o
| (k = x
1
| ( k = x
2
| (k = x
3
| (k = x
4
) || ocorre k [... x
n-1
]))))
...
k = x
o
| (k = x
1
| ( k = x
2
| (k = x
3
| (k = x
4
) | ... ocorre k [x
n-1
])))))
k = x
o
| (k = x
1
| ( k = x
2
| (k = x
3
| (k = x
4
) | ... | (k = x
n-1
)| ocorre k [ ])))))
Figura 15.4 desenvolvimento da computao da ocorrncia de
um elemento em uma lista
Main> o1orre 5 [8,65,46,23,99,35]
False
(71 reductions, 111 cells)
Main> o1orre 5 [8,65,46,5,23,99,35]
True
(47 reductions, 58 cells)
Main> o1orre 5 [ ]
False
(16 reductions, 30 cells)
ExempIo 04 - Descrever a funo que obtm de uma lista xs a sublista formada pelos
elementos que so menores que um dado k :
SoIuo : Precisamos descrever uma nova lista, vamos denomin-la de !enores,
em funo de xs e de k. Quem ser esta nova lista? Se o primeiro elemento de xs for
menor que k, ento ele participar da nova lista, que pode ser descrita como sendo
formada pelo primeiro elemento de xs seguido dos menores que k no resto de xs. Se por
outro lado o primeiro no menor que k, podemos dizer que a lista resultante obtida pela
aplicao de menores ao resto da lista. Novamente a base da recurso definida pela lista
vazia, visto que em uma lista vazia no ocorrem elementos menores que qualquer k.
A codificao apresentada a seguir:
--
-- define a lista de menores que um dado elemento em
-- uma lista dada
--
menores 8 ,s = if null ,s
then ,s
else if hea% ,s 2 8
then hea% ,s : menores 8 &tail ,s)
else menores 8 &tail ,s)
Desta podemos obter as seguintes avaliaes:
Main> menores 23 [8,65,46,5,23,99,35]
[8,5]
(122 reductions, 188 cells)
Main> menores 46 [8,65,46,5,23,99,35]
[8,5,23,35]
(135 reductions, 175 cells)
Main> menores 5 []
[]
(17 reductions, 24 cells)
16.6. EXPLORANDO REUSO: Segundo o Professor George Polya, aps concluir a
soluo de um problema, devemos levantar questionamentos a respeito das possibilidades
de generalizao da soluo obtida. Dentro deste esprito, vamos explorar um pouco a
soluo obtida para o problema descrito a seguir.
ExempIo 5 (Sub-Iista de nmeros pares): Dada uma lista xs, desejamos descrever
uma sublista de xs formada apenas pelos nmeros pares existentes em xs.
137
SoIuo: Devemos considerar a existncia de suas situaes, como no problema de
encontrar a sublista dos menores (Exemplo 4):
1. O primeiro elemento da lista um nmero par, neste caso a sublista resultante
dada pela juno do primeiro com a sublista de pares existente no resto da lista.
2. O primeiro no par. Neste caso a sublista de pares em xs obtida pela seleo
dos elementos pares do resto de xs.
Concluindo, tomemos como base da recurso a lista vazia, que obviamente no
contm qualquer nmero.
Eis a soluo em HUGS:

--
-- sublista de nmeros pares
--
slpares ,s = if null ,s
then ,s
else if e+en &hea% ,s)
then hea% ,s : slpares &tail ,s)
else slpares &tail ,s)
E a avaliao de algumas instncias:
Main> slpares [1..10]
3!(4(6(.(1'5
(322 reductions, 438 cells)
Main> slpares [1,3..100]
35
(962 reductions, 1183 cells)
Vamos agora, seguindo as orientaes do mestre Polya, buscar oportunidades de
generalizao para esta funo. Podemos fazer algumas perguntas do tipo:
1. Como faria uma funo para determinar a sublista dos nmeros mpares a
partir de uma dada lista?
2. E se quisssemos a sublista dos primos?
3. E que tal a sublista dos mltiplos de cinco?

Uma breve inspeo na soluo acima nos levaria a entender que a nica diferena
entre as novas funes e a que j temos a funo que verifica se o primeiro elemento
satisfaz uma propriedade, no caso presente a de ser um nmero par (even), conforme
destacamos a seguir:

138
--
-- sublista de nmeros pares
--
slpares ,s = if null ,s
then ,s
else if e+en &hea% ,s)
then hea% ,s : slpares &tail ,s)
else slpares &tail ,s)
--
-- sublista de nmeros impares
--
slimpar ,s = if null ,s
then ,s
else if o%% &hea% ,s)
then hea% ,s : slimpar &tail ,s)
else slimpar &tail ,s)
--
-- sublista de nmeros primos
--
slprimo ,s = if null ,s
then ,s
else if primo &hea% ,s)
then hea% ,s : slprimo &tail ,s)
else slprimo &tail ,s)
sto nos sugere que a funo avaliadora pode ser um parmetro. Pois bem,
troquemos ento o nome da funo por um nome mais geral e adicionemos sua interface
mais uma parmetro. Este parmetro, como sabemos, dever ser do tipo:

alfa -> Doolean
Vejamos ento o resultado da codificao, onde a propriedade a ser avaliada se
converte em um parmetro:
--
-- sublista de elementos de xs que satisfazem
-- a propriedade prop
--
su?lista prop ,s = if null ,s
then ,s
else if prop &hea% ,s)
then hea% ,s : su?lista prop &tail ,s)
else su?lista prop &tail ,s)
Vejamos ento algumas aplicaes na nossa funo genrica para determinar
sublistas:
139
Main> sublista e+en [1..10]
[2,4,6,8,10]
Main> sublista o%% [1..10]
[1,3,5,7,9]
Main> sublista &2") [1..10]
[1,2,3,4]
Main> sublista &>=") [1..10]
[5,6,7,8,9,10]
Observe que a funo que havamos anteriormente definido para determinar os
elementos menores que um determinado valor k, da mesma forma que a funo para
determinar os maiores que k, est contemplada com a nossa generalizao. As duas
ltimas avaliaes no quadro acima ilustram a determinao da sublista dos valores
menores que 5 e a dos maiores ou iguais a 5.
Exerccios:
Descreva funes em HUGS que utilizem recurso para resolver os problemas abaixo.
1. Obter a interseo de duas listas xs e ys.
2. Dadas duas strings xs e ys, verificar se xs prefixo de ys.
3. Dadas duas strings xs e ys, verificar se xs sufixo de ys.
4. Dadas duas strings xs e ys, verificar se xs sublista de ys.
5. inverter uma lista xs;
6. Definir a funo tWhile, que tenha o mesmo comportamento que a funo
takeWhile.
7. Definir a funo dWhile, que tenha o mesmo comportamento que a funo
dropWhile.
8. Verificar se uma string um palndrome (a string a mesma quando lida da
esquerda para a direita ou da direita para a esquerda).
9. Verifique se uma string uma palavra. Defina uma palavra como formada apenas
por letras.
10. Verificar se os elementos de uma lista so distintos.
11. Determinar a posio de um elemento x em uma lista xs, se ele ocorre na lista.
12. Descrever a lista das palavras que existem no texto, dado um texto.
13. Dadas duas listas xs e ys, ordenadas em ordem crescente, obter a lista ordenada
resultante da intercalao de xs e ys.
14. Calcular a combinao de uma lista xs, p a p.
140
17. ORDENAO RECURSVA DE DADOS, ALGUNS PROBLEMAS
CORRELATOS E ALGUMAS TCNCAS DE PROPSTO GERAL
17.1 - INTRODUO: Voltemos ento ao problema de ordenar os elementos de uma
lista, para o qual j discutimos uma soluo no paradigma aplicativo.
=ada u!a lista xs deseja!os descre$er sua ordena34o#
Vamos comear propondo e resolvendo um problema mais simples.
Insero ordenada: Dada uma lista ordenada xs e um elemento k desejamos
descrever uma lista a partir de xs, na qual esteja includo o valor k, com a condio de que
a nova lista tambm esteja ordenada.
SoIuo : Voltemos a nossa estratgia para obter solues recursivas. Aqui tambm
temos dois casos:
1. O valor k menor que o primeiro da lista xs, neste caso a lista resultante descrita
pela juno de k com a lista xs;
2. O valor k maior ou igual ao primeiro elemento da lista xs, neste caso a lista
resultante descrita pela juno do primeiro da lista xs com a lista obtida pela
insero ordenada de k no resto da lista xs.
A codificao pode ser realizada da seguinte forma:
--
-- insero ordenada de um valor k em uma
-- lista ordenada (no decrescente)
--
insord k xs = if null xs
then [k]
else if k < head xs
then k : xs
else head xs : (insord k (tail xs))
141
k < x
0
k
:
Xs
Caso contrrio x
0 :
insord k

Xs
insord k Xs =
Figura 17.1 insero ordenada de um
elemento k em uma lista Xs
E a seguir algumas aplicaes da soluo:
Main> insor% 5 [0,2..10]
3'(!(4("(6(.(1'5
(230 reductions, 407 cells)
Main> insor% 5 [10,15..50]
3"(1'(1"(!'(!"(3'(3"(4'(4"("'5
(248 reductions, 379 cells)
Main> insor% 5 [-10,15..0]
3-1'("5
(92 reductions, 135 cells)
Main> insor% 5 [-10,-5..0]
3-1'(-"('("5
(154 reductions, 220 cells)
Main> insor% 5 []
3"5
(23 reductions, 32 cells)
Agora j podemos voltar ao nosso problema inicial de ordenao de listas. Vamos em
busca de uma primeira soluo:
SoIuo : A ordenao no decrescente de uma lista xs qualquer igual insero
ordenada do primeiro da lista na ordenao do resto da lista.
--
-- ordenao de uma lista
--
ordena xs = if null xs
then xs
else insord (head xs) (ordena (tail xs))
Vejamos a aplicao da soluo algumas instncias:
Main> or%ena [3, 4, 50,30,20,34,15]
33(4(1"(!'(3'(34("'5
(241 reductions, 330 cells)
Main> or%ena [100,93..50]
3"1(".(6"(#!(#0(.6(03(1''5
(568 reductions, 780 cells)
17.2 DIVISO E CONQUISTA (UMA TCNICA PODEROSA): Alguns problemas possuem
solues mais facilmente descritas, algumas at mais eficientes, quando quebramos o
problema em partes menores, descrevemos a soluo de cada parte e depois combinamos
as solues parciais para obter a soluo completa. Este mtodo denominado de
"diviso e conquista". Basicamente buscamos encontrar instncias do problema onde a
soluo seja imediata. . Nesta seo veremos alguns exemplos desta abordagem. O
primeiro deles, a pesquisa binria, trata da busca de um elemento em uma lista ordenada.
Os outros dois, mergesort e quicksort, apresentam solues alternativas para a ordenao
de uma lista.
142
17.2.1. PESQUISA BINRIA - Voltemos a um problema j apresentado
anteriormente, verificao da ocorrncia de um elemento a uma lista. Segundo a definio
que apresentamos para a funo ocorre, apresentada no exemplo 3 do Captulo 16.
Podemos constatar que para avaliar expresses onde o elemento procurado no ocorre na
lista, o avaliador de expresses precisar fazer uma quantidade de comparaes igual ao
comprimento da lista considerada. Na mdia de um conjunto de avaliaes, considerando
as avaliaes de expresses em que o elemento procurado est na lista, e que a cada vez
estaremos procurando por um elemento distinto, teremos um nmero mdio de
comparaes da ordem de (n / 2). Se n for muito grande ficaremos assustados com o
nmero de comparaes. Por exemplo, para uma lista de 1000000 (um milho) de
elementos, em mdia teremos que fazer 500 mil comparaes.
Se pudermos garantir que a lista est ordenada, ento podemos fazer uso de uma
estratgia j discutida anteriormente para reduzir este nmero. Estamos falando da rvore
binria de pesquisa. A estratgia que usaremos consiste em, a cada passo de reduo,
abandonarmos metade da lista considerada a partir da comparao de k com o elemento
que se encontra na metade da lista. Se o elemento buscado (k) for igual ao elemento
central, ento o processo de avaliao est encerrado. Quando isto no ocorre, devemos
ento escolher em qual lista devemos procur-lo. Quando ele menor que o elemento
central devemos busc-lo na sublista que antecede o central, caso contrrio devemos
busc-lo na sublista dos seus sucessores. Novamente a base da recurso determinada
pela lista vazia.
Nesta abordagem, a cada escolha abandonamos metade da lista restante. Desta
forma, o nmero de comparaes dado pelo tamanho da seqncia:

n@$, n@%, n@B, ??? , n@n
Para simplificar a anlise podemos escolher um n que seja potncia de 2. Neste caso
podemos assegurar que o comprimento da seqncia dado por:

To( n na base %
Voltando ento ao nmero de comparaes necessrias para localizar um elemento,
podemos constatar que em uma lista com 1 milho de elementos, ao invs das 500 mil
comparaes da soluo anterior, precisaremos no pior caso, de apenas 20 comparaes.
sso mesmo, apenas 20. Vamos ento codificao em HUGS:

--
-- pesquisa binria
--
pesqbin k xs = if null xs
then False
else if k == pivot
then True
else if k < pivot
then pesqbin k menores
else pesqbin k maiores
where
p = div (length xs) 2
menores = take p xs
maiores = tail (drop p xs)
143
pivot = head (drop p xs)
E a seguir, a avaliao de algumas instncias:
Main> o1orre 1023 [0..1023]
True
(24592 reductions, 32797 cells)
Main> pesq?in 1023 [0..1023]
True
(71563 reductions, 92060 cells)
17.2.2 MERGESORT - Existem outras maneiras de se descrever a ordenao de uma
lista. Uma delas, denominada !er,esort, se baseia na intercalao de duas listas j
ordenadas. Comecemos ento por discutir a intercalao que, em si mesmo, j representa
uma ferramenta intelectual bastante interessante.
IntercaIao: Antes de ver o mergesort podemos apresentar uma verso recursiva
para a intercalao de duas listas em ordem no decrescente.
SoIuo: A intercalao de duas listas ordenadas xs e s pode ser descrita atravs
de dois casos:
1. se o primeiro elemento de xs menor que o primeiro elemento de s ento a
intercalao dada pela juno do primeiro elemento de xs com a
intercalao do resto de xs com s;
2. caso contrrio, a intercalao descrita pela juno do primeiro elemento de
s com a intercalao do resto de s com xs;
A codificao resultante pode ser observada a seguir:
--
-- Intercala duas listas em ordem no decrescente
--
intercala xs ys = if (null xs) || (null ys)
then xs ++ ys
else if head xs <= head ys
then head xs : intercala (tail xs) ys
else head ys : intercala xs (tail ys)
E a seguir, algumas submisses e avaliaes do HUGS:
Main> inter1ala [1,3..10] [0,2..10]
3'(1(!(3(4("(6(#(.(0(1'5
Main> inter1ala [0,2..10] [1,3..10]
3'(1(!(3(4("(6(#(.(0(1'5
Main> inter1ala [0,2..10] []
[0,2,4,6,8,10]
Main> inter1ala [] []
ERROR: Unresolved overloading
144
*** Type : Ord a => [a]
*** Expression : intercala [] []
Main> inter1ala [] [0,2..10]
3'(!(4(6(.(1'5
Main> inter1ala [0,2..10] [0,2..10]
3'('(!(!(4(4(6(6(.(.(1'(1'5
Main> inter1ala [9,7..1] [10,8..1]
30(#("(3(1(1'(.(6(4(!5
(o que houve que no ficou ordenada?)
Voltemos ao mergesort, ou, em bom portugus, ordenao por intercalao.
SoIuo : A ordenao de uma lista por mergesort igual intercalao do
mergesort da primeira metade da lista com o mergesort da segunda metade. Esta soluo
explora a noo de rvore binria. Neste caso, a lista original dividida em 2 partes, cada
uma delas em outras duas e assim sucessivamente at que esta quebra no seja mais
possvel. A figura Fig. 17.1 ilustra o processamento da ordenao de uma lista.

145
Vejamos ento como fica a codificao em HUGS.
--
-- ordena uma lista pela intercalao da ordenao de
-- suas duas metades
--
mergesort xs = if null (tail xs)
then xs
else intercala (mergesort m) (mergesort n)
where
m = take k xs
n = drop k xs
k = div (length xs) 2
Main> mergesort [1..10]
[1,2,3,4,5,6,7,8,9,10]
(1593 reductions, 2185 cells)
Main> mergesort [10,9..1]
[1,2,3,4,5,6,7,8,9,10]
(1641 reductions, 2236 cells)
17.2.3. QUICKSORT - Existe uma maneira muito famosa de resolver o mesmo
problema de ordenao, usando ainda a noo de diviso e conquista, muito parecida com
o mergesort. mplementaes desta soluo reduzem sensivelmente o nmero de
comparaes necessrias e so, portanto muito utilizadas.
SoIuo : Na verso usando o mergesort dividamos a instncia original exatamente
ao meio. Nesta vamos dividir tambm em duas, mas com seguinte critrio: a primeira com
os elementos menores que um elemento qualquer da lista e a segunda com os elementos
maiores ou iguais a ele. Este elemento denominado pi$ot e existem vrias formas de
escolh-lo. A melhor escolha aquela que produzir as sublistas com comprimentos bem
prximos, o que repercutir no desempenho da avaliao. Aqui nos limitaremos a escolher
como pivot o primeiro elemento da lista. Assim sendo, aps obter a ordenao das duas
listas, basta juntar a ordenao da primeira, com o pivot e finalmente com a ordenao da
segunda. A figura Fig. 9.2 ilustra a aplicao do quicksort a uma instncia do problema.
146
E a seguir vejamos a codificao.
quicksort xs = if (null xs) || (null (tail xs))
then xs
else quicksort (sublista (< pivot) (tail xs))
++ [pivot]
++ quicksort (sublista (>= pivot) (tail xs))
where
pivot = head xs
Convidamos o leitor a apreciar e discutir a elegncia, a compacidade e a clareza da
descrio do quicksort.
Vejamos a avaliao de algumas instncias:
Main> qui18sort [4,5,6,7,8,3,2,1]
[1,2,3,4,5,6,7,8]
(595 reductions, 755 cells)
Main> qui18sort [1..10]
[1,2,3,4,5,6,7,8,9,10]
(1536 reductions, 1881 cells)
Main> qui18sort [10,9..1]
[1,2,3,4,5,6,7,8,9,10]
(1541 reductions, 1952 cells)
147
Figura 17.1 desenvolvimento da computao da funo
palndromo
Main> mergesort [10,9..1]
[1,2,3,4,5,6,7,8,9,10]
(1647 reductions, 2283 cells)
Main> mergesort ,s == qui18sort ,s where xs = [1..10]
True
(2805 reductions, 3563 cells)
Main> mergesort [2,14,16,23,29,35,47,68,70,90]
[2,14,16,23,29,35,47,68,70,90]
(1414 reductions, 1922 cells)
Main> qui18sort [2,14,16,23,29,35,47,68,70,90]
[2,14,16,23,29,35,47,68,70,90]
(1357 reductions, 1618 cells)
Main> or%ena [2,14,16,23,29,35,47,68,70,90]
[2,14,16,23,29,35,47,68,70,90]
(236 reductions, 336 cells)
17.3. PROCESSAMENTO DE CADEIAS DE CARACTERES: As cadeias de caracteres,
como j vimos, tambm so listas, portanto o uso de recurso com cadeias segue as
mesma recomendaes. Para ilustrar vamos apresentar alguns exemplos.
ExempIo 01 - [Palndromo] Dada uma cadeia de caracteres verifique se um
palndromo. Segundo o dicionrio, um palndromo uma frase ou palavra, que no
importando o sentido que se l, significa a mesma coisa. Por exemplo, "Socorram-me subi
no nibus em Marrocos". Vejam que a quantidade de espaos, os separadores e os
trminos de palavra no so considerados. Aqui vamos tratar a questo de forma
simplificada, os separadores sero tratados como caracteres comuns.
SoIuo : Neste caso, importante observar que podemos olhar a cadeia como
sendo formada por pares de valores eqidistantes dos extremos. Um cadeia palndromo
se os seus extremos so iguais e o meio da lista um palndromo. A base da recurso so
as cadeias vazias ou aquelas com apenas um elemento.
Vejamos ento a codificao em HUGS e a avaliao para algumas instncias.

E agora uma avaliao de algumas listas candidatas a palndromo:
x
0
=

x
n-1
& palndromo [x
1
, x
2
, x
3
, x
4
, x
5
, ..., ]
x
0
=

& (x
1 =
x
n-1
&

palndromo [ x
2
, x
3
, x
4
, x
5
, ..., ] )
x
0
=

& (x
1 =
x
n-1
&

( X
2
= X
n-2
& palndromo [x
3
, x
4
, x
5
, ..., ] ))
palndromo [x
0
, x
1
, x
2
, x
3
, x
4
, x
5
, ..., x
n-1
]
148
--
-- Verifica se uma sentena Palndromo
--
--
palindromo xs = if null xs || null (tail xs)
then True
else (head xs == last xs) &&
palindromo (meio xs)
where
meio xs = init (tail xs)
Seguindo nosso padro de apreentao,vejamos como ficam algumas avaliaes:
Main> palin%romo "socorrammesubinoonibusemmarrocos"
*rue
(687 reductions, 698 cells)
Main> palin%romo "socorram-me subi no onibus em marrocos"
False
(891 reductions, 907 cells)
Main> palin%romo "ama"
*rue
(31 reductions, 43 cells)
Main> palin%romo "papagaio"
False
(29 reductions, 45 cells)
Main> palin%romo "arara"
*rue
(49 reductions, 61 cells)
ExempIo 02 - [Prefixo] Dadas duas cadeias de caracteres verifique se a primeira
idntica subcadeia formada pelos primeiros caracteres da segunda. Por exemplo, "aba"
prefixo da cadeia "abacaxi" e "pre" prefixo de "prefixo".
SoIuo : De imediato podemos dizer que uma cadeia xs prefixo de uma cadeia ys
quando:
iii) o primeiro elemento de xs igual ao primeiro elemento de ys e;
iv) o restante de xs prefixo do restante de ys.
v)
Quanto base da recurso, temos que considerar duas situaes:
i) A primeira tem como base que a cadeia vazia prefixo de qualquer outra cadeia;
ii) A segunda leva em conta que nenhuma cadeia pode ser prefixo de uma cadeia
vazia (exceto a cadeia vazia).
Vejamos como fica em Haskell:
149
--
-- Verifica se uma cadeia xs prefixo
-- de uma segunda (ys)
--
prefixo xs ys = if null xs
then True
else if null ys
then False
else (head xs == head ys) &&
prefixo (tail xs) (tail ys)
As avaliaes de expresses a seguir nos permitem observar o funcionamento de
nossa descrio:
Main> prefi,o "aba" "abacadraba"
True
Main> prefi,o "" "abacadraba"
True
Main> prefi,o "pre" "prefixo"
True
Main> prefi,o "prefixo" "pre"
False
Main> prefi,o "prefixo" ""
False

ExempIo 03 - [Casamento de Padro] Verificar se uma cadeia satisfaz um
determinado padro um processamento muito til e constantemente realizado na prtica
da computao. Aqui nos ateremos a uma forma simplificada deste problema que consiste
em verificar se uma cadeia su+cadeia de outra.
SoIuo : Uma rpida inspeo nos leva constatao de que o problema anterior
parecido com este, exceto pelo fato de que a primeira cadeia pode ocorrer em qualquer
lugar da segunda. Podemos dizer ento que a primeira cadeia ocorre na segunda se ela
um prefixo da primeira ou se ela ocorre no resto da segunda.
Vejamos como fica em HUGS:
--
-- Verifica se uma cadeia xs subcadeia
-- de uma outra (ys)
--
subcadeia xs ys = if null ys || null (tail ys)
then False
else prefixo xs ys || subcadeia xs (tail ys)
A avaliao das expresses a seguir ajuda no entendimento:
150
Main> su?1a%eia "" "prefacio"
*rue
Main> su?1a%eia "pre" "prefacio"
*rue
Main> su?1a%eia "cio" "prefacio"
*rue
Main> su?1a%eia "efa" "prefacio"
*rue
Main> su?1a%eia "acido" "prefacio"
False
Main> su?1a%eia "efa" ""
False
Exerccios:
1. Pesquise como descrito o mtodo da "bolha para ordenao. Faa
uma funo em Haskell para ordenar uma lista pelo mtodo da bolha.
151
18. APLICAES
Neste captulo apresentamos uma srie temtica de exerccios, buscando dar ao leitor uma
viso mais ampla das possibilidades de uso da programao funcional. A inteno
apresentar vrios contextos onde precisamos programar computadores. Em todos, o
contexto descrito e vrios exerccios so apresentados. Aos professores e estudantes,
sugerimos que o contexto sirva de pretexto para a formulao e resoluo de novos
exerccios. Comeamos pelo Domin Bar, onde, buscamos na ludicidade do jogo,
apresentar as necessidades de manipular informao. Na seqncia apresentamos uma
srie de problemas considerando as necessidades de informao de um Banco de
Sangue, o manuseio de mensagens de um Correio EIetrnico, a organizao de uma
Lista de Compras, um sistema de Passagens Areas, Gerncia Acadmica, Agncia
de Turismo e exerccios sobre EspetcuIos Teatrais.
18.1 O DOMIN BAR: O domin de nmeros uma coleo de pedras, utilizado na
maioria das vezes como um excelente passatempo. Das tantas formas de utilizar o
domin, destacamos uma, utilizada no Amazonas, principalmente em Manaus, mas
tambm em muitas praias pelo mundo afora onde existirem amazonenses, em particular
nas praias de Fortaleza. Os Amazonenses costumam cham-la de "domin bar", em
homenagem a uma tribo que habitava a regio onde foi fundada a cidade de Manaus. A
maioria dos exerccios deste captulo foram desenvolvidos em Manaus, no final da dcada
de 80. De l pra c, vrios outros foram acrescentados, mas a lista como um todo
permanece indita.
A inteno desta seo apresentar alguns poucos exerccios resolvidos e propor outros.
A idia no desenvolver o jogo e sim, inspirar-se em situaes do jogo para propor
exerccios interessantes e desafiadores. Deixamos o desenvolvimento do jogo completo
como sugesto para o trabalho em grupos. Ao final do captulo discutiremos um pouco
sobre a programao do jogo.
PreIiminares: O material do jogo um conjunto formado por 28 "peas", cada uma delas
com duas "pontas". Cada "ponta" representa um valor de 0 (zero) a seis (6), perfazendo
portanto 7 valores diferentes. Cada valor possui um nome prprio: o Zero chama-se
"branco", o um chama-se "s", o dois o "duque", o trs chama-se "terno", o quatro a
"quadra", o cinco a "quina" e o seis denomina-se "sena". O nome de uma "pedra" dado
pelo nome de suas "pontas", por exemplo, "quina e terno", o nome da "pedra" que possui
em uma ponta o valor 5 e na outra o valor 3. As pedras que possuem o mesmo valor nas
duas pontas so denominadas de "carroa". Para cada tipo de valor existem 7 pedras, por
exemplo, para o "terno" teremos: terno e branco, terno e s, terno e duque, carroa de
terno, quadra e terno, quina e terno, sena e terno. O jogo , em geral, disputado por
duplas, ganhando a que fizer o maior numero de pontos, a partir de um mnimo pr-
estabelecido. A seguir apresentamos em detalhes os vrios elementos do jogo.
Peas do Jogo: Os elementos do jogo so (28) vinte e oito peas, cada uma com duas
pontas, na qual marcado um valor que varia de 0 a 6. Para jogar, as "pedras" so
embaralhadas e escolhidas pelos jogadores. A cada jogador cabem 7 pedras. Com o
desenrolar do jogo a quantidade de pedras vai sendo decrescida, at que, eventualmente
chegue em zero.
152
Participantes: duas duplas (eventualmente pode ser jogado individualmente, com 2, 3 ou
4 jogadores).
Objetivo: atingir um total mnimo de 200 pontos. Vence o jogo a dupla que ao final de uma
rodada tiver o maior nmero de pontos.
Dinmica: o jogo se desenvolve em uma quantidade qualquer de eventos menores
denominados de rodada. A figura 18.1 ilustra um instante de jogo.
Rodada: em uma rodada, um aps o outro, no sentido horrio, os jogadores vo fazendo
suas jogadas, combinando suas pedras de domin com a "figura que j est formada na
mesa de jogo.
Pontuao: existem 4 formas para obter pontos:
1. Durante o jogo, a figura formada na mesa possui 1 (quando existe apenas uma pea
assentada), 2, 3 ou 4 pontas. soma dos valores dessas pontas denomina-se de:
"os pontos da mesa. Quando essa soma produz um mltiplo de 5, o jogador que
sentou a ltima pedra pode requerer que eles sejam anotados em favor de sua
Figura 18.1 um instante do jogo de domin, com quatro pontas abertas:
terno, s, duque e quadra.
153
dupla. Veja que s o jogador que sentou a pedra pode reivindicar os pontos e isto
tem que ocorrer antes que o prximo jogador sente a sua pedra;
2. Quando um jogador no possui pedra para colocar na mesa (ou seja, uma que
combine com uma das pontas), ele passa a vez, e a dupla adversria ganha 10
pontos. Se um jogador percebe que com a colocao de sua pea ele conseguir
fazer com que todos os demais passem, inclusive o seu parceiro, ele pode anunciar
que deu um passe geral e com isso ganhar de bnus 50 pontos.
3. Quando um jogador descarta sua ltima pea em uma rodada diz-se que ele
"bateu, e, portanto ganhou a rodada. Com isso ele ganha de bnus 10 pontos e
mais o mltiplo de 5 ligeiramente inferior soma dos valores constantes nas peas
que sobraram nas mos dos adversrios (garagem). Se a batida for feita com uma
carroa, o bnus de 20 pontos.
4. Quando ocorre uma situao onde nenhum dos jogadores consegue jogar, embora
estejam com peas na mo, diz-se que o jogo est fechado. Neste caso ganha a
rodada a dupla cuja soma dos valores das peas for o menor. A soma das peas da
dupla adversria computada em seu favor, como no caso 3.
Posio dos Jogadores: Os membros de cada dupla so colocados em posies
alternadas, de forma que as jogadas (colocao de peas) seja feita de forma alternada
entre as duplas adversrias. Por exemplo, em um jogo presencial, podemos usar, como
suporte para colocao das peas, uma mesa de quatro lugares, ficando os parceiros
sentados frente-a-frente.
Distribuio das Peas: a distribuio das 28 peas entre os 4 jogadores deve ser feita
de forma aleatria. Na prtica, em um jogo com peas fsicas, viram-se as peas de cara
para baixo e mistura as peas com as mos. Cada jogador vai retirando as suas prprias
peas.
Quem comea uma rodada: Uma rodada sempre iniciada com a colocao de uma
"carroa. Na primeira rodada do jogo, a carroa a ser utilizada de sena (6), cabendo pois
ao jogador que a tirou comear o jogo. As rodadas seguintes so iniciadas pelo jogador
que bateu a rodada anterior, com a carroa que ele preferir. Se ele no possui carroa, ele
passa e o jogador seguinte (da dupla adversria) inicia o jogo, se este tambm no
possuir, passa a frente.
Uma Jogada: Estando na sua vez de jogar, o jogador deve escolher uma das pedras de
sua mo, e coloca-la na mesa de jogo, combinando com alguma das pontas abertas. A
escolha da pea a ser jogada deve contribuir para o objetivo da dupla que ganhar o jogo,
isso significa, em linhas gerais, escolher uma pedra que me permita fazer o maior nmero
de pontos e, quando isso no for possvel, escolher uma pedra que reduza o nmero de
pontos que os adversrios possam fazer com base em minha jogada. H, entretanto
algumas nuances a serem consideradas:
Quando eu jogo fazendo pontos devo buscar maximizar meus pontos e minimizar os
que o jogador adversrio possa fazer a partir da minha jogada;
Se o jogo estiver prximo do trmino, e a dupla adversria ameaa completar os
200 pontos, pode ser desejvel adiar o trmino, no fazendo os pontos. Por
exemplo, suponha que a dupla adversria tem 185 pontos e a minha 130. Se eu
tiver uma pea na mo que faz 25 pontos, mas se possvel ao adversrio possuir
154
uma pea que lhe permita fazer 15 pontos, eu posso escolher outra pea, deixando
assim de obter os 25 pontos;
Quem abre uma rodada, bater a rodada a menos que passe. Tendo em vista que
ao ganhar uma rodada, h bnus para a dupla, posso deixar de marcar ponto
visando vencer a rodada;
dem para tentar evitar que a dupla adversria ganhe a rodada (quando foro a
passada de um adversrio que comeou a rodada, a batida passa para o meu
parceiro).
Um passe geral d um bnus de 50 pontos, isso pode me levar a busc-los, desde
que as condies do jogo, definidas pelas peas de minha mo, combinadas com o
que j foi jogado, se mostrem propcias.
Exerccios: A seguir apresentamos alguns exerccios, baseados no domin. Para fins
didticos separamos em grupos.
Grupo I
1. Escreva a funo pedrap que associe um par a True se e somente se (sss) o par
uma representao vlida para uma "pedra" e FaIse caso contrrio.
ExempIos de uso:
1. pedrap (2, 7) ==> FaIse
2. pedrap ((-3), 4) ==> FaIse
3. pedrap (3,4) ==> True
SoIuo:
pedrap (x,y) = validap x && validap y
validap x = elem x [0..6]
2. Escreva a funo maop que associe uma lista de pares de inteiros a True sss a lista
uma representao vlida para a "mo" de um jogador e FaIse caso contrrio.
ExempIos de uso:
1. maop [ ] True
2. maop [((-3), 4)] FaIse
3. maop [(3,4)] True
4. maop [ (1,2), (1,5), (2,0), (2,4), (3,3), (1,1), (0,0), (4,0)] FaIse
SoIuo:
maop [ ] = True
maop (x:xs) = (length xs <= 6) && pedrap x && maop xs
155
3. Escreva a funo carrocap que associe um par a True sss o par uma "carroa" e
FaIse caso contrrio.
4. Escreva a funo tem_carroca_p que associe uma "mo" a True sss a mo possuir
pelo menos uma carroa e FaIse caso contrrio.
5. Escreva a funo tem_carrocas que associe a uma "mo" a lista das "carroas"
nela contida.
Grupo II
Em vrios momentos do jogo faz-se necessrio saber a quantidade de pontos
associado uma coleo de pedras. Em particular, no final do jogo, quem "sentou" a
sua ltima pedra faz jus "garagem" que determinada a partir dos pontos que
restaram na(s) mo(s) dos adversrios.
6. Escreva a funo pontos que associe uma lista de "pedras" a soma dos pontos das
pedras nela contidos. Onde os pontos de uma pedra a soma de suas pontas.
SoIuo:
pontos [ ] = 0
pontos (x:xs) = ponto x + pontos xs
where
ponto (x,y) = x + y
7. Escreva a funo ,ara,e! que associe uma lista de "pedras" ao maior mltiplo de 5
(cinco), menor ou igual soma dos pontos nela contidos.
8. Escreva a funo pedraVi,ualVp que associe dois pares de inteiros a True sss
representam a mesma pedra e FaIse caso contrrio. bom lembrar que a ordem
das pontas irrelevante, assim (2,4) e (4,2) representam a mesma pedra.
9. Escreva a funo ocorreVpedraVp que associe uma "pedra" e uma "mo" a True
sss a "pedra" ocorre na "mo" e FaIse caso contrrio.
10. Escreva a funo ocorreV$alorVp que associe um valor vlido para "ponta" e uma
"mo" e produza True sss o valor ocorre em alguma pedra da mo e FaIse caso
contrrio.
11. Escreva a funo ocorreVpedra que associe a um valor e uma "mo", uma lista
contendo as pedras da "mo" que possuem o valor dado.
12. Escreva a funo pedraV!aior que associe uma "mo" a pedra de maior valor na
"mo" dada. Uma pedra p1 maior que uma outra p2 sss a soma das pontas de p1
for maior que a soma das pontas de p2.
13. Escreva a funo ocorreV$alorVq que associe um valor e uma "mo" e produza o
nmero de pedras na mo que possuem o valor dado.
14. Escreva a funo ocorreVcarrocaVq queassocie uma mo quantidade de
carroas nela existentes.
15. Escreva a funo tiraV!aior que associe uma mo a uma lista similar "mo" de
onde foi extrada a pedra de maior ponto.
156
16. Escreva a funo tiraV!aiorV$ que associe um valor e uma "mo" lista similar
"mo" de onde se extraiu a pedra de maior pontos de um determinado valor para
ponta.
Grupo III
O jogo se desenvolve pela colocao, pelo Jogador da vez, de uma pedra que combine
com alguma das "pontas" da "mesa". Num momento genrico do jogo temos quatro pontas
disponveis para execuo de uma jogada. Uma ponta pode ser simples ou uma carroa.
As carroas so dispostas de tal forma que todos os seus pontos estejam para "fora".
Chamaremos "mesa" lista de pontas disponveis para jogada. Pontas simples sero
representadas por listas de um elemento e carroas por uma lista com dois elementos
idnticos. Por exemplo, a "mesa" ilustrada na Figura 18.2 representada pela qudrupla
( [5,5], [5], [0],[4] ).
Uma ponta ainda no aberta representada por lista vazia. Dizemos que h marcao de
pontos em uma mesa quando a soma das pontas um mltiplo de 5. Os pontos a serem
marcados a soma das pontas, com as carroas contando em dobro.
Figura 18.2 desenvolvimento do jogo, no instante em que temos nas
pontas externas, uma carroa de quina, uma quina, branco e quadra.
157
17. Escreva a funo !esap que associe uma qudrupla de listas a True sss a
qudrupla for uma descrio vlida de "mesa".
SoIuo:
mesap (p1,p2,p3,p4) = vponta p1 && vponta p2 &&
vponta p3 && vponta p4
where
vponta (x:y:xs) = if not (null xs)
then FaIse
eIse validap x && vponta (y:xs)
vponta (x :[ ] ) = validap x
validap x = elem x [0..6]
18. Escreva a funo carrocaV!Vp que associe uma mesa a True sss pelo menos uma
das pontas for carroa.
19. Escreva a funo pontosV!arcados que associe uma mesa ao o nmero de
pontos a serem marcados se a soma das pontas for mltiplo de cinco e zero em
caso contrrio.
20. Escreva a funo podeVjo,asVp que associe uma "pedra" e uma "mesa" a True
sss a pedra possui uma ponta que combina com pelo menos uma das pontas da
mesa.
21. Escreva a funo !arcaVpontoVp que tenha como entrada uma "pedra" e uma
"mesa" e produza True sss a pedra pode ser jogada fazendo pontos em uma das
pontas da mesa. Lembre-se que as carroas devem ser contadas pelas duas pontas
da pedra.
22. Escreva a funo !aiorVponto que tenha associa uma pedra e uma mesa ao
nmero da "ponta" da mesa onde pode ser marcado o maior valor de ponto que ser
marcado pela pedra. Considere que a em uma "mesa" as pontas so numeradas a
partir de zero, da esquerda para a direita.
23. Escreva a funo jo,aVpedra que associe uma "pedra", uma "mesa" e um nmero
de "ponta" da mesa a uma nova mesa obtida ao se jogar a "pedra" na "ponta"
indicada.
24. Escreva a funo jo,ap que associe uma "mo" e uma "mesa" e produza True sss
existe pelo menos uma pedra na mo que possa ser jogada em pelo menos uma
ponta da mesa. Caso contrrio produza FaIse.
25. Escreva a funo jogada que associe uma "mo" e uma mesa ao nmero da pedra
na mo e nmero da ponta na mesa onde pode ser feita a jogada que marque mais
ponto. Considere inclusive jogada onde no h marcao de ponto.
26. Escreva a funo faz_jogada que associe uma "mo" e uma "mesa" e produza uma
nova "mesa" obtida por se jogar marcando o maior nmero de pontos possvel
18.2 Banco de Sangue: para facilitar o atendimento da demanda por transfuses de
sangue o sistema de sade criou os chamados Bancos de Sangue. Como sabemos, cada
transfuso s pode ser realizada usando tipos de sangue apropriados. A adequao de um
determinado tipo de sangue baseada em estudos cientficos que identificou quatro tipos
158
sangneos, denominados de 2, W, 2W e M. Outros estudos identificaram ainda a
existncia do chamado fator RH que pode ser positivo (+) ou negativo (-), assim o sangue
de qualquer indivduo classificado de acordo com esses dois atributos. Por exemplo,
dizemos que fulano possui sangue tipo O e fator RH positivo, e abreviamos para O+. Em
um dado Banco de Sangue, diariamente, so feitas doaes por pessoas de diferentes
tipos sangneos, para as quais feito um registro contendo o nmero da carteira de
identidade do doador (RG), o sexo (S), a data da doao (DD), a data de nascimento (DN),
o tipo sangneo (TS), o fator RH (RH) e a quantidade doada (QD) (250 ou 500 ml). O
sangue doado guardado em recipientes com uma capacidade fixa (250 ml). Tambm,
diariamente so feitas requisies pelos hospitais (H), cada requisio indica as
caractersticas do sangue (tipo e fator RH) e a quantidade solicitada (QS). Sabemos que
homens e mulheres possuem intervalos de tempo diferentes para fazer doaes. Para
homens o intervalo mnimo de 2 (dois) meses e para mulheres de 3 (trs). A idade
mxima para doadores 60 anos.
Sejam as seguintes estruturas
Doao (RG, S, DD, DN, TS, RH, QD)
Requisio (H, TS, RH, QS)
Exerccios: Escreva programas em HUGS para resolver os seguintes problemas:
1. Dada uma lista de doaes, obtenha a quantidade total de sangue doado por tipo
sangneo e fator RH. O resultado ser uma tupla (um item para cada combinao de
tipo sangneo com fator RH) com triplas explicitando o tipo sangneo, o fator RH e a
quantidade total. Quando no houver doao de uma dado par tipo-fator deve ser
indicado o valor zero. Por exemplo:
( ('A', '+', 0), ... ('O','+', 5500) ...)
2. Para uma dada lista de doaes, determine a lista dos dias de um dado ms onde as
doaes foram menores que a mdia mensal.
3. Dada uma lista de doaes e a data atual, determine a lista de doadores que j esto
aptos a fazerem novas doaes.
4. Dada a lista de doadores e o ms, determinar o nmero de doadores que esto aptos a
doar sangue naquele ms. (Essa e a questo 3 parecem anlogas, no?)
5. Determine a relao de doadores que fazem doaes com o maior ndice de
regularidade. O ndice de regularidade dado pela nmero de vezes que o intervalo
entre as doaes coincidem, dividido pelo nmero de doaes menos um.
6. Dada a lista de doadores, verificar o tipo sangneo que mais comumente doado.
7. Dada a lista de doadores e o ano, determine o ms em que houve mais doaes
naquele ano.
159
8. Dada a lista de requisies de um determinado hospital, determinar a lista de tipos
sangneos com os respectivos fatores RH, que possuem seus pedidos atendidos pelo
banco de sangue.
9. Determinar, para um dado hospital em um determinado ano, a demanda mensal de
sangue, por tipo sangneo e fator RH.
10. Determinar a lista de doadores que no esto mais aptos a fazer doaes,
considerando a data atual.
11. Considere o estoque atual do banco de sangue, determinado pela funo estoque (prob
1), e uma lista com vrias requisies. Leve em conta que o estoque pode ser
insuficiente para atender completamente todos os pedidos. Determine o estoque
atualizado aps o atendimento dos pedidos e produza uma lista das requisies
atendidas, constando a quantidade que foi de fato fornecida.
12. No problema 11, considere que voc deseja atender cada hospital solicitante, de forma
proporcional ao seu pedido, considerando os pedidos de cada tipo sangneo
separadamente. Por exemplo, suponha que: o total de pedidos de sangue O+ de
12.000 ml, que o hospital "h1 solicitou 3.000 ml de sangue O+ e que no estoque 8.000
ml. Podemos observar que o pedido para o sangue O+ do hospital "h1 representa 25
% do total. Neste caso o hospital "h1 ser atendido com 25 % de 8.000 ml que
representa 2.000 ml. Produza uma lista como os pedidos atendidos e outra com os
pedidos pendentes.
13. Considere a poltica de atendimento do problema 12 mas leve em conta que um dado
pedido deve ser atendido completamente. Considere o exemplo do problema anterior, e
suponha que os pedidos do hospital 'h1' para o sangue O+ so 4, ("h1, O, +, 1.500),
("h1, O, +, 1.000) e ("h1, O, +, 250) e ("h1, O, +, 500). Neste caso, considerando que
os pedidos esto em ordem de prioridade, seriam atendidos os pedidos ("h1, O, +,
1.500) e ("h1, O, +, 250).
14. Modifique a poltica de atendimento do problema 14 para que o atendimento seja tal
que o hospital "h1 use da melhor forma possvel a proporcionalidade que lhe cabe. No
caso do exemplo apresentado no problema 14, o pedido de 250 ml seria descartado
visto que atendendo o pedido de 500 ml o hospital 'h1 estar usando melhor a parte
que lhe cabe. (escolher a combinao mais apropriada)
18.3 Correio EIetrnico: Considere um sistema de mensagens eletrnicas. Uma
mensagem pode ser descrita por uma tupla contendo o remetente, o destinatrio, a data de
envio, o assunto e o corpo da mensagem. Mensagens podem ser acumuladas em listas
para posterior acesso. Para facilitar o acesso podemos construir ndices baseados nos
dados contidos na mensagem. Por exemplo, podemos ter um ndice baseado no remetente
para facilitar o acesso a todas as mensagens de um dado remetente. Considere as
seguintes estruturas:
mensagem (remetente, destinatrio, data, assunto, corpo)
ndice [ (argumento1,[ordem na lista de mensagens]), (argumento2, []), ...]
160
Exerccios: Elabore programas em HUGS, usando recurso, para atender aos seguintes
problemas. A interface (nome e parmetros) das funes dado em cada uma das
questes.
1. (indexa msgs) Dada uma lista de mensagens, produza o ndice das mensagens por
remetente. Um ndice ter a seguinte estrutura: [ (remetente1, lista de ocorrncias),
(remetente2, lista de ocorrncias), ...] onde lista de ocorrncias formada pela posio
na lista de mensagens onde o remetente ocorre.
Por exemplo:
[ ("jose@inf.ufes.br, [1, 23]), ("maria@inf.ufes.br, [10, 20, 50]), ...]
2. (consulta r p) Considere definidos um ndice por remetente, um ndice por palavras
constantes no assunto das mensagens e uma lista de mensagens. Dados um
remetente (r) e uma palavra(p), obtenha a lista de mensagens enviadas por r onde a
palavra p ocorre no assunto.
remetentes = [("remetente1, [...]),("remetente2, [...]), ... ]
palav_assunto = [ ("palavra1. [...]),("palavra2. [...]), ... ]
mensagens = [ mensagem11 mensagem21 mensagemL1 ]
3. (msgPmes a r msgs) Dado um ano (a), um remetente (r) e uma lista de mensagens
(msgs), verificar a quantidade mensagens enviadas por r em cada ms.
4. (busca p ind msgs) Considere um ndice construdo na forma de lista (indb). O primeiro
elemento um par com uma palavra (p) e a lista de mensagens (msgs) onde p ocorre,
o segundo elemento uma lista no mesmo formato de indb, para as palavras menores
que p e o terceiro para as palavras maiores que p
ndice = [ (palavra1, [...]), ndice para palavras menores que p, ndice para palavras
maiores que p]
Quando no houver palavras menores ou maiores que uma dada palavra, o ndice
igual a uma lista vazia.
Fada uma pala7ra p1 o =ndice (indb) e a lista de mensagens (msgs)1 descre7a a lista
mensagens onde p ocorre1 usando o =ndice dado
5. (palavPassunto msgs) Considere definida uma lista de palavras irrelevantes (lis). Dada
uma lista de mensagens (msgs) produza um ndice com as palavras distintas que
ocorrem nos assuntos das mensagens e no ocorrem em lis. Para cada palavra deve
ser produzido tambm a lista das posies na lista de mensagens (msgs) onde ela
ocorre.
lis = [ "palavra1, "palavra2. ... ]
6. (releva msgs li lf) Dada uma lista de mensagens podemos obter uma lista de palavras
relevantes. Define-se como palavra relevante em uma lista mensagens (msgs) aquelas
161
cuja freqncia satisfazem um intervalo para o qual so dados um limite superior (ls) e
um limite inferior (li).
7. (constante msgs a) Dada uma lista de mensagens (msgs), determinar a lista de
remetentes que enviaram pelo menos uma mensagem para cada ms de um dado ano
a.
8. (freqData msgs m) Para uma dada lista de mensagens desejamos obter a quantidade
de mensagens para cada dia de um dado ms m.
9. (identico indb1 indb2) Dados dois ndices no formato de rvore binria de pesquisa
desejamos verificar se so idnticos. Dizemos que dois ndices so idnticos quando a
palavras e as listas de ocorrncia coincidem e os subndices das palavras menores e o
das palavras maiores respectivamente so idnticos.
ndice = ( (palavra1, [...]),
ndice para palavras menores que p, ndice para palavras maiores que p)
10. (palavOrd indb) Dado um ndice no formato de rvore binria de pesquisa produza uma
lista das palavras nele contidas de tal forma que as palavras se apresentem em ordem
alfabtica crescente.
11. (resgate indb) Dado um ndice no formato de rvore binria de pesquisa produza uma
lista das palavras que ocorrem em cada mensagem. A lista resultante ter o seguinte
formato:
[ [palavras da mensagem de ordem 0], [palavras da mensagem de ordem 1 ], ... ]
12. (balance arbinpq) Uma rvore binria de pesquisa est balanceada se e somente se a
quantidade (q1) de elementos no subindice das palavras menores difere da quantidade
(q2) de elementos no subindice das palavras maiores de no mximo um (1) e q1
maior ou igual a q2.
q2 + 1 %= q1 %= q2
13. (insOrd indb msg) Dados um ndice (indb) no formato de rvore binria de pesquisa e
uma mensagem (msg), descreva a nova rvore obtida pela insero das palavras das
mensagem (msg), exceto as irrelevantes.
14. (perfil msg diret fga) Um diretrio uma lista de assuntos, cada um dos quais
associado a uma coleo de palavras. Dada uma mensagem e um diretrio podemos
atribuir mensagem um perfil que uma lista de valores indicando o grau de
aproximao (ga) dela com cada assunto. O ga de uma mensagem com respeito a um
assunto pode ser obtido com base na freqncia com que as palavras a ele associadas
ocorrem na mensagem. Considere que a funo que calcula o ga fornecida e opera
sobre uma lista de inteiros.
Considere os seguintes formatos:
Diretrio M (Nassunto1O1 Mpala7ra11 pala7ra21 P)1 (Nassunto2O1 Mpala7ra11 pala7ra21 P)1 P
Perfil M (Nassunto1O1 ga1)1 (Nassunto2O1ga2)1 P
162

18.4 Lista de Compras: Para realizar um determinado projeto necessitamos adquirir
certos componentes eletrnicos. No mercado de componentes existem vrios fornecedores
que vendem seus produtos com preos diferenciados. A escolha da melhor alternativa
para satisfao de nossas compras depende de vrios fatores, dos quais o melhor preo
um dos mais importantes.
Considere as seguintes definies:
Tabela de
Preo
Uma lista contendo todos os preos dos componentes comercializados por um
determinado revendedor. Cada elemento da lista um par no formato
(material, preo).
Exemplo:
[("potenciometro, 2.50), ("resistor-100k, 0.30), ("capacitor-10mF,0.50), ("indutor-
10R,3.00)]
Pedido de
Compra
Uma lista contendo todos os materiais necessrios para um determinado projeto,
com suas respectivas quantidades. Cada elemento da lista um par no formato
(material, quantidade).
Exemplo: [("transformador, 50), ("fonte DC, 10), ("resistor-200k,100)]
Lista de
Revendedores
Uma lista contendo a tabela de preos de todos os revendedores, no formato:
[ (revendedor1, [tabela de preo] ), ...]

Exerccios: Elabore programas em HUGS, usando recurso, para atender aos
seguintes problemas. O nome das funes dado em cada uma das questes.
1. (custo) Dado o resultado da pesquisa de preos de um pedido de compra, para um
certo fornecedor, no formato [ (material1, qtde, preo), (material2, qtde, preo), ... ],
queremos obter o custo total da compra se optarmos por esse fornecedor.
2. (fornece) Dado um pedido de compra e a tabela de preos de um determinado
revendedor, obtenha a lista dos materiais que ele pode fornecer.
3. (subprojeto) Considere os pedidos de compra para dois projetos (p1 e p2).
Eventualmente alguns itens do pedido do projeto p1 podem ocorrer no pedido de p2,
possivelmente com quantidades distintas. Dizemos que um projeto p1 subprojeto de
p2 se cada componente de p1 tambm componente de p2 em quantidade idntica ou
inferior.
4. (lfornecedor) Dado um pedido de compra e a lista de revendedores, descrever a lista de
fornecedores para cada componente, com seus respectivos preos, no formato
[(material1,[rev1, rev2,...] ), (material2, [...]), ...]
18.5 Gerncia Acadmica: Considere a gerncia acadmica dos cursos de graduao de
uma universidade. As disciplinas cursadas por um aluno so registradas em seu histrico.
O registro deve conter o cdigo da disciplina, o ano e o semestre em que foi cursada e a
nota obtida. Semestralmente o aluno deve requerer matrcula em novas disciplinas. O
pedido de matrcula realizado atravs da apresentao das disciplinas desejadas pelo
aluno. Um dos critrios para conseguir se matricular em uma disciplina que o aluno
tenha cumprido, com aprovao, os pr-requisitos da disciplina. Um aluno aprovado em
uma disciplina se obtiver mdia superior ou igual a 5 (cinco). Cada curso possui uma grade
curricular que relaciona cada disciplina do curso com seus respectivos pr-requisitos.
163
Considere as seguintes definies:
Histrico Escolar Um par contendo o cdigo de matrcula do aluno e a lista de
disciplinas cursadas. !ada disciplina cursada representada por
uma tripla com o cdigo da disciplina, o ano e o semestre que ela
foi cursada e a nota obtida.
"ormato# $matrcula, % $disciplina, $ano, semestre&, nota&, ... '&
onde
matrcula ( $ano, curso, n)mero*dentifica+o*ndi,idual&
!adastro de
-isciplinas
Uma lista contendo, para cada disciplina, um par com o cdigo da
disciplina e a quantidade de crditos.
Grade !urricular Um par com o cdigo do curso e uma lista de pares onde cada par
representa uma disciplina $cdigo& e uma lista dos seus pr.
requisitos.
"ormato# $curso, %$disciplina, %disciplina, disciplina,...'&, ...'&
/edido de matrculaUm par com o cdigo do aluno e uma lista contendo o cdigo das
disciplinas nas quais o aluno dese0a se matricular.
"ormato# $matrcula, %pedido1, pedido2, ...'&
Oferta Uma lista contendo as turmas a serem ofertadas, com seus 3or4rios
e limite de ,agas.
"ormato# %$disciplina, turma, quantidade5de5,agas, 3or4rio&,...'
onde
3or4rio ( %$dia5da semana, 3ora5inicial, 3ora5final&, ...'
6ista de disciplinas
de um curso,
apresentadas por
perodo
Um par contendo o cdigo do curso e uma lista de pares, onde cada
par representa um perodo do curso e uma lista das disciplinas do
perodo.
"ormato# $curso, %$perodo, %disciplina, disciplina,...'&
Histrico
Escolar
Um par contendo o cdigo de matrcula do aluno e a lista de
disciplinas cursadas. Cada disciplina cursada representada
por uma tripla com o cdigo da disciplina, o ano e o semestre
que ela foi cursada e a nota obtida.
Formato: (matrcula, [ (disciplina, (ano, semestre), nota), ... ])
onde
matrcula = (ano, curso, registro)
Cadastro de
Disciplinas
Uma lista contendo, para cada disciplina, um par com o cdigo
da disciplina e a quantidade de crditos.
Grade
Curricular
Um par com o cdigo do curso e uma lista de pares onde cada
par representa uma disciplina (cdigo) e uma lista dos seus pr-
requisitos.
Formato: (curso, [(disciplina, [disciplina, disciplina,...]), ...])
Lista de
disciplinas de
um curso,
apresentadas
por perodo
Um par contendo o cdigo do curso e uma lista de pares, onde
cada par representa um perodo do curso e uma lista das
disciplinas do perodo.
Formato: (curso, [(perodo, [disciplina, disciplina,...])
Exerccios: Escreva funes em Hugs para resolver os problemas propostos abaixo,
usando os nomes indicados em negrito. 7 pala,ra semestre, nestes problemas, representa
um elemento do tipo $ano,s&, onde s ( 1 ou s ( 2.
164
1. (credse) Dado um histrico, o cadastro de disciplinas e um semestre, descrever o total
de crditos cumpridos no semestre.
2. (ncred) Dado um histrico e o cadastro de disciplinas, descrever a quantidade de
crditos cumpridos por semestre.
3. (dncursadas) Dado um histrico e uma lista com as disciplinas por perodo, descrever
a lista das disciplinas no cursadas ainda pelo aluno, dos perodos j cumpridos. Esta
lista deve ter o seguinte formato: [(perodo,[disciplina,..]),(perodo,[disciplina,...]),...]
4. (maxcred) Dada uma lista de histricos, identificar a lista de alunos que possuem o
maior nmero de crditos cumpridos.
5. (conterep) Dado um histrico, contar o nmero de reprovaes.
6. (jubiIa) Verificar se um determinado aluno se encontra em situao de jubilamento
(possui trs reprovaes em uma mesma disciplina).
7. (abandono) Verificar se o aluno deixou de cursar disciplinas em algum semestre.
8. (divida) Obter a lista das disciplinas que foram cursadas por um dado aluno, nas quais
ele ainda no obteve aprovao.
9. (reprova) Obter uma lista de reprovaes por perodo, para um dado aluno.
10. (crend) O coeficiente de rendimento (CR) de um dado aluno determinado pela
mdia ponderada das notas obtidas, tendo como peso, o nmero de crditos das
disciplinas. Determine o CR de um dado aluno.
11. (semprereq) Obter uma lista das disciplinas de um dado curso, que no possuem
pr-requisito.
12. (cumprereq) Dada uma disciplina, verificar se o aluno cumpriu seus pr-requisitos.
13. (dividas) Obter para um dado aluno, a lista de disciplinas que ele ainda no cursou,
com respeito a uma dada grade curricular.
14. (sugestao) Obter para um dado aluno, a lista de disciplinas que ele est apto a
cursar, com respeito a uma dada grade curricular.
15. (Icumprereq) Obter uma lista de pedidos de disciplinas para as quais os pr-
requisitos foram cumpridos.
16. (IdiscsoI) Dada uma lista com os pedidos de todos os alunos, obtenha uma lista
das disciplinas solicitadas, sem repetio.
17. (soI_discipIinas_ord) Obter a lista de alunos que solicitaram uma dada disciplina,
com seus respectivos coeficientes de rendimentos. A lista de alunos deve estar em
ordem crescente por coeficiente de rendimento. A lista resultante deve ter o seguinte
formato:
[(aluno1, coeficiente_de_rendimento1),(aluno2, coeficiente_de_rendimento2), ...]
18.6 Agncia de Turismo: Uma agncia de turismo possui o mapa atualizado de reservas
dos hotis de uma determinada regio. Para cada hotel, todas as informaes pertinentes
aos tipos de quarto oferecidos so registrados no mapa. Este mapa representado por
uma lista de tuplas, seguindo o seguinte formato:
165
[(nome_hoteI, [(tipo_quarto, vaIor_diria, situao), ...] ), ...] onde
nome_hoteI do tipo string;
tipo_quarto uma string;
vaIor_diria um nmero real positivo;
situao: nmero inteiro positivo que indica a quantidade de quartos livres do tipo
indicado.
Para o melhor entendimento da representao da lista de hotis no hugs, considere o
seguinte exemplo:
lhoteis = [("peterle", [("simples", 50.0, 5),("duplo", 75.8, 10), ("luxo", 110.0, 2)] ),
("ibis", [("simples", 45.0, 3),("duplo", 65.5, 15), ("luxo", 95.0, 3)] ),
("novotel", [("simples", 65.6, 10),("duplo", 90.5, 20), ("luxo", 150.0, 10)] )]
Exerccios: Considerando o formato desta lista de hotis apresentada acima, resolva o
seguinte problema, descrevendo funes em HUGS.
1. Dados um tipo de quarto e a lista de hotis, apresente a lista com o nome do hotel ou
com os nomes dos hotis que possuem a oferta mais barata para aquele tipo de quarto.
2. Avalie a funo definida no problema 1 para os parmetros adequados, considerando a
lista de hotis como a dada acima.
18.7 EspetcuIos Teatrais: Vrios espetculos esto sendo apresentados em um grande
teatro da cidade. Para cada um dos espetculos, registra-se o mapa de ocupao da
platia, conforme as vendas dos ingressos. A platia est representada por m filas
numeradas de 1 a m, sendo que cada fila contm n cadeiras tambm numeradas de 1 a n
Considere a seguinte representao para os dados:
Lugar na platia ('ila, cadeira)# onde 'ila 2 representada por um inteiro de 1 a m e
cadeira# por um inteiro de 1 a n.
Platia 3ista de duplas (lu(ar, situao) sendo que a situa&o 2 : 1 para
indi"ar lugar o"upado e 0 para indi"ar lugar vago.
Teatro 3ista de duplas (es"etbculo, "lat!ia) onde es"etbculo 2 representado
por um inteiro de 1 a p.
Exerccios: Escreva um script em HUGS, com funes que resolvam os problemas
abaixo. Nomes para cada uma das funes so sugeridos ao final do enunciado de cada
problema.
5. Dada uma platia pls, descreva a quantidade total de lugares ocupados (totalOcup).
6. Dado um lugar lg e uma platia pls, verifique se o lugar lg est livre (estaLivre).
7. Dado um lugar lg e uma platia pls, verifique se existe algum vizinho lateral de lg que
est livre (vizinhoLivre).
166
8. Dada uma fila fl e uma platia pls, descreva a lista de cadeiras livres da fila fl
(cadeirasLivresFila).
9. Dada uma platia pls, descreva a lista de cadeiras livres para cada fila (lugLivresFila)
10. Dada uma platia pls, descreva a(s) lista(s) com o maior nmero de cadeiras livres
(filaMaxLivre).
11. Dado um teatro trs e um espetculo ep, descreva a sua platia (plateiaEsp).
12. Dado um teatro trs, um espetculo ep e uma fila fl, descreva a lista de cadeiras livres da
fila fl (cadeirasLivresFilaEsp).
167
19. ENTRADA E SAIDA DE DADOS
19.1 INTRODUO:
Os programas que apresentamos e propusemos at ento, se basearam em um padro
especfico de interao entre o usurio e o sistema. O interpretador HUGS est
constantemente solicitando uma expresso, que em seguida avaliada por ele e o
resultado apresentado ao usurio. Vejamos o modelo ilustrado na figura 20.1. A avalio
de uma expresso leva em conta as definies disponveis em bibliotecas e as construdas
pelos programadores.
Algumas
vezes
entretanto este modelo de interao no adequado tendo em vista que o programa do
usurio no pode tomar a deciso de pedir ou no um dado ao usurio. Tudo tem que ser
informado antecipadamente.
ExempIo 1: Desejamos fazer um programa que interaja com o usurio para que ele
tente descobrir um nmero oculto. A interao do programa s deve continuar enquanto o
jogador no descobrir o nmero oculto. E veja, no d para antecipar antes e codificar isto
em uma expresso. A Figura 20.2 mostra um esquema da interao necessria. O
programa pode comear pedindo um valor ao usurio. Se o usurio fornece um valor
idntico ao valor oculto, o programa exibe a mensagem anunciando que o jogador venceu
e encerra o jogo. Caso contrrio o programa solicita um novo palpite.
168
usurio
Interpretador
HUGS
expresso
resuItado
Figura 20.1 Modelo de nterao usurio-interpretador HUGS
scripts
Nestes casos, no queremos descrever mapeamentos entre conjunto de valores e
sim seqncia de aes. o contato das funes com o mundo. Ainda podemos usar
funes para determinar valores, mas quando precisamos, temos que estabelecer uma
seqncia de aes a serem executadas. Agora o que nos interessa definir programas,
atravs de seqncias de aes.
Vejamos uma soluo para o joguinho acima introduzido:
jogo1 = do
putStrLn ">>fornea um nmero entre 0 e 10"
valor <- getLine
if valor == "5"
then do putStrLn "acertou - parabns!"
else do putStrLn "errou - tente outra vez!"
jogo1
sim
no
"Fornea outro vaIor"
vaIor
"Jogo encerrado"
VaIor fornecido
=
Nmero ocuIto
?
Figura 20.2 nteraes para descobrir um nmero
oculto
169
E algumas interaes:
Main> jogo1
>>fornea um nmero entre 0 e 10
3
errou - tente outra vez!
>>fornea um nmero entre 0 e 10
4
errou - tente outra vez!
>>fornea um nmero entre 0 e 10
2
errou - tente outra vez!
>>fornea um nmero entre 0 e 10
5
acertou - parabns!
Vamos agora dissecar o programa:
1. Para estabelecer contato com o mundo precisamos de uma ao para leitura e
outra para exibio de resultado. Aqui a leitura realizada atravs da primitiva
getLine. Para exibir resultados fazemos uso da primitiva putStrLn. Enquanto
getLine no precisa de um parmetro, visto que uma ao que sempre buscar
na interao obter um valor, a putStr necessita de um valor para ser exibido;
2. O programa jogo1 no precisa de parmetro para realizar sua atividade, dado que
tudo ser solicitado diretamente dentro do corpo do programa, na medida do
necessrio;
3. Para informar que o que estamos definindo uma seqncia de aes e no uma
descrio funcional, introduzida a partcula do, que pode ser traduzida pelo
imperativo faa!
4. Para que um valor obtido pelo comando de leitura getLine, se torne disponvel
para uso do programa precisamos internaliz-lo atravs do uso da primitiva
representada pelo smbolo ";
valor getLine
5. Para indicar que desejamos continuar executando o programa podemos fazer uma
chamada a ele mesmo, como o fizemos em:
else %o putKtrAn "errou - tente outra vez!"
>ogo1
170