Você está na página 1de 119

ë  p p 

p p 
    

Até agora lidamos com as linguagens de


PROGRAMAÇÃO ORIENTADA A COMANDO,
chamadas de IMPERATIVAS
Fortemente afetadas pela
arquitetura dos computadores convencionais

Œ
Em vez disso, as linguagens de
PROGRAMAÇÃO FUNCIONAL baseiam-se na
TEORIA DAS FUNÇÕES MATEMÁTICAS
ppp
p p  
   
ë 

A motivação das linguagens funcionais
não é a eficiência da execução
e sim os seguintes aspectos:

Qual é a mais apropriada


unidade de decomposição de um programa ?

Como uma linguagem de programação


pode dar um melhor suporte à
composição de componentes independentes?
pp
p p  
   
ë 

Nas LPs procedurais, as unidades de decomposição
são os procedimentos (procedures),
que podem causar efeitos colaterais,
?
nas estruturas globais que comunicam-se entre si

Tipos abstratos de dados tentam


modularizar um programa,
pelo empacotamento de dados e de operações,
para limitar o escopo dos efeitos colaterais,
nas unidades encapsuladas ?
A programação funcional baseia-se sem
nas funções matemáticas, variável
operando sobre valores e ?
produzindo valores, sem qqr efeito colateral
p p  
    pp

ë 
1
Inicialmente, serão abordadas as principais
diferenças da programação funcional, ilustradas
pelos conceitos básicos da programação imperativa

Para salientar mais ainda essas diferenças,


as funções matemáticas serão comparadas com
as funções das linguagens imperativas

2 em seguida vamos apresentar


a linguagem de programação funcional:
HASKELL
pp
p p  
   
ë 
As linguagens de programação funcional primitivas,
começando por LISP,
adotavam escopo e tipagem dinâmicas

Scheme é um dialeto de LISP,


que adotou escopo estático na linguagem

Mais tarde, linguagens funcionais, tais como ML,


Haskell, adotaram não somente escopo estático
mas também tipagem forte

Haskell é puramente funcional,


não tendo variáveis nem comando de atribuição.
Assim, não inclui recursos imperativos e
não produz efeitos colaterais.
p p  
    pp
p p   

  
 

ë 

As linguagens de programação imperativa


são caracterizadas por três conceitos:
variáveis, atribuição e seqüência de execução

O estado de um programa imperativo


é mantido em variáveis de programa

Essas variáveis são associadas a alocações de


memória, que são caracterizadas por:
um endereço (l-value) e
um valor armazenado (r-value)

O acesso ao valor de uma variável pode ser


direto via seu l-value ou APONTADOR
indiretamente via o r-value de uma outra variável
p p  
    pp
p p   

  
 

ë 
As linguagens de programação imperativa
são caracterizadas por três conceitos:
variáveis, atribuição e seqüência de execução

O valor de uma variável é alterado na execução de um


comando de atribuição

O comando de atribuição introduz uma ordem de


dependência no programa: o valor de uma variável
pode ser diferente antes e depois da execução de um
comando de atribuição
ATRIBUIÇÃO
Os efeitos em um programa, então, e seqüência
de execução
DEPENDEM DA ORDEM em que
os comandos são escritos e executados
p p  
    pp
p p   

  
 

ë 
As linguagens de programação imperativa
são caracterizadas por três conceitos:
variáveis, atribuição e seqüência de execução

Na matemática, variáveis são amarradas a valores


e uma vez amarradas, não trocam de valores

Assim, o valor de uma função INDEPENDE dos


conceitos da programação imperativa, como por
exemplo, A ORDEM DA EXECUÇÃO DOS COMANDOS

Uma função matemática define um mapeamento de


um valor de domínio para um valor de faixa
p p  
    pp!
p p   

  
 

ë 

FUNÇÃO MATEMÁTICA é
um conjunto de pares ordenados que relaciona cada
elemento no domínio com um único correspondente
elemento na faixa
Œ
FUNÇÃO na PROGRAMAÇÃO IMPERATIVA é
descrita como algoritmo que especifica
como computar os valores da faixa
para um valor de domínio em uma
DETERMINADA SEQÜÊNCIA DE PASSOS
Lembrando que as linguagens de programação
imperativa são caracterizadas por três conceitos:
variáveis, atribuição e seqüência de execução
p p  
    pp
"
p p   

  
 

ë 
REPETIÇÃO (LOOP) é uma outra característica das
linguagens imperativas, usada, freqüentemente, para
computar os valores desejados

Os loops são usados, por exemplo, para:


U varrer uma seqüência de alocações de memória
(p/ex. arrays)
U acumular o valor de uma dada variável

Em contraste, em funções matemáticas,


os valores são computados pela aplicação de função

RECURSÃO é usada no lugar de ITERAÇÃO

COMPOSIÇÃO DE FUNÇÃO é usada para


construir funções mais poderosas
p p  
    pp

p p   

  
 

ë 

Por causa das diferentes características

As LINGUAGENS IMPERATIVAS
são chamadas de BASEADAS EM ESTADO
ou
ORIENTADA A COMANDO

As LINGUAGENS FUNCIONAIS
são chamadas de
BASEADAS EM VALORES
ou
APLICATIVAS
p p  
   
CONCEITO p p 
p
p p #
$ %   
ë 
Uma função é uma regra para mapeamento de
membros de um conjunto domínio para um conjunto
faixa Ex. função quadrado poderia mapear elementos
do conjunto inteiro p/conjunto natural

A definição de uma função é constituída de duas


partes: uma assinatura e uma regra de mapeamento

A assinatura especifica o domínio e a faixa

A regra de mapeamento especifica o valor da faixa


associado a cada valor de domínio

quadrado: inteiro ¢ natural Assinatura.


EX
quadrado(n) š n  n Regra de mapeamento.
p p  
   
DEFINIÇÃO p p 

p p #
$ %   
ë 

quadrado: inteiro ¢ natural Assinatura.


EX
quadrado(n) š n  n Regra de mapeamento.

Atenção: na literatura aparece


o símbolo ƒ para denotar ´é definida comoµ,
mas aqui está sendo usado o símbolo = adotado em
Haskell.

Então, encontra-se também:

quadrado: inteiro ¢ natural Assinatura.


quadrado (n) ƒ n  n .Regra de mapeamento
p p  
   
DEFINIÇÃO p p 

p p #
$ %   
ë 

quadrado: inteiro ¢ natural Assinatura.


EX
quadrado(n) š n  n Regra de mapeamento.

função nomeada quadrado, acima, definida


como o mapeamento de elementos do conjunto
inteiro p/conjunto natural

símbolo š em Haskel significa ´é definida comoµ


n é um parâmetro, que representa
qualquer membro do conjunto do domínio

nas definições de função, por convenção,


a assinatura é omitida se
domínio e faixa são implícitos no contexto
p p  
    p p 
APLICAÇÃO
p p #
$ %   
ë 

quadrado: inteiro ¢ natural Assinatura.


EX
quadrado(n) š n  n Regra de mapeamento.

Uma vez definida uma função, ela pode ser aplicada a


qualquer membro do conjunto domínio

A aplicação produz (ou resulta, ou retorna) o elemento


associado na faixa

No momento da aplicação, um elemento particular do


domínio é especificado

Esse elemento, chamado o argumento, substitui o


argumento da definição
p p  
   
APLICAÇÃO p p 

p p #
$ %   
ë 

quadrado: inteiro ¢ natural Assinatura.


EX
quadrado(n) š n  n Regra de mapeamento.

A substituição é puramente textual

Se a definição contém aplicações, ?


elas são aplicadas na seqüência até ser alcançada uma
expressão que possa ser avaliada para produzir o
resultado da aplicação original

quadrado (2) produz o valor 4


de acordo com a sua definição
p p  
   
APLICAÇÃO p p 

p p #
$ %   
ë 

quadrado: inteiro ¢ natural Assinatura.


EX
quadrado(n) š n  n Regra de mapeamento.

O parâmetro n é uma variável matemática Œ?


diferente de uma variável de programa

Na definição da função, n representa


qualquer membro do conjunto domínio

Na aplicação da função, é dado um valor específico,


que nunca é trocado

Em contraste, a variável de programa, no paradigma


imperativo, pode assumir diferentes valores durante o
curso da execução de um programa
p p  
    pp
COMBINAÇÃO
p p #
$ %   
ë 
DE FUNÇÕES

Novas funções podem ser criadas pela


COMBINAÇÃO DE OUTRAS

A forma mais comum de combinação de funções é a


COMPOSIÇÃO

Se uma função F é definida como a composição de


duas funções G e H, escrita como F š G ` H,
a aplicação de F é definida pela
aplicação de H e então
a aplicação de G para
chegar finalmente ao resultado
p p  
    ë 
p p #
$ %  pp
  !
Nas LPs convencionais,
uma função é definida proceduralmente

A regra de mapeamento de um valor do domínio para


um valor de faixa é determinada em termos de
passos que necessitam ser executados em uma certa
ordem especificada pela estrutura de controle

Contraste entre convencionais e funcionais

Por outro lado, as funções matemáticas são


DEFINIDAS APLICATIVAMENTE

Muitas funções matemáticas são definidas


recursivamente, i.e, a definição da função contém
uma aplicação da própria função
p p  
    RECURSÃO p p p
"
p p #
$ %   
ë 
Muitas funções matemáticas são definidas recursivamente, i.e, a
definição da função contém uma aplicação da própria função

Por exemplo, a definição matemática padrão de


fatorial de um número natural é
n! = if n = 0 then 1 else n* (n-1)!

Outro exemplo é a possibilidade de formular uma


função recursiva p(n, i), de números naturais para
booleano, que coopera para determinar se um número
é primo prime (n) = if n = 2 then true else p(n, n div 2)
Essa função auxiliar p(n,i) produz true se n não tem
divisor na faixa 2..i,
p( n, i ) é recursiva
p (n, i) = if (n mod i) = 0
then false else if i = 2 then true else p (n, i-1)
p p  
    RECURSÃO p p p

p p #
$ %   
ë 
função recursiva, de números naturais para booleano, que
determina se um número é primo
prime (n) ƒ if n = 2 then true else p(n, n div 2)

A função auxiliar p(n,i) produz true se n não tem


divisor na faixa 2..i, p( n, i ) é
recursiva
p (n, i) ƒ if (n mod i) = 0
then false else if i = 2 then true else p (n, i-1)

Notar como a chamada recursiva p (n, i-1) assume o


papel da iteração adotada no loop de um programa
imperativo

Recursão é uma técnica poderosa para solução de


problemas, usada pesadamente em programação com
funções
p p  
    ppp
p
ë 
p p  
   &
A programação funcional tem
três componentes primários:
1) Um conjunto de objetos de dados
2) Um conjunto de funções embutidas

3) Um conjunto de formas funcionais ordem


alta
nas expressões ?
(também chamadas funções de alta ordem)
para a construção de novas funções
Obs.: iunções de alta ordem aceitam uma ou mais
funções, como entrada/saída de uma função.
Funções de alta ordem aceitam uma ou mais funções, como
entrada/saída de uma função.
]   
         
  
 mapeia uma função para outra
            
         
         
         
         
      
! @      "#  
   
    ]  $    
           
    %      
        
  $            
           & 
   
  ' 
%         
       ( ))*
p p  
    ppp

p p  
   & ë 

A programação funcional tem três


componentes primários:

1) Um conjunto de objetos de dados

Tradicionalmente, as linguagens de
programação funcional oferecem um
mecanismo de estruturação de dados
exclusivo de alto nível tal como uma lista ou
um array
p p  
    ppp

p p  
   & ë 

A programação funcional tem três


componentes primários:

2) Um conjunto de funções embutidas

Essas funções tratam os objetos de dados


básicos

Por exemplo:

As LPs funcionais oferecem um número de


funções para construção de acesso a listas
p p  
    ppp
p p  
   & 
ë 
A programação funcional tem três componentes primários:

3) Um conjunto de formas funcionais nas


expressões
(também chamadas de funções de alta ordem)
para a construção de novas funções
Estilo de programação baseado no uso de funções

Todas as expressões são baseadas em funções


(funções podem ser argumentos de outras funções)

Toda a programação é baseada na


avaliação de expressões para gerar valores
(cada valor tem um tipo associado, que pode ser implícito)
p p  
    ppp

p p  
   & ë 

A programação funcional tem três componentes primários:

3) Um conjunto de formas funcionais nas


expressões
(também chamadas de funções de alta ordem)
para a construção de novas funções

Um exemplo bastante comum de uma expressão é a


composição de função ´°µ

Outro exemplo comum é a redução de função

A forma funcional da expressão reduce aplica uma


função binária pelos sucessivos elementos de uma
seqüência
p p  
    p p  
    ppp
 &
3) Um conjunto de formas funcionais (também chamadasëde
funções de
alta ordem) para a construção de novas funções

A forma funcional reduce aplica uma função binária pelos


sucessivos elementos de uma seqüência

Por exemplo:
( reducing + sobre um array produz a soma dos
elementos do array
( reducing * sobre o array produz o produto dos
elementos do array

Em APL, / é a forma funcional de redução (chamada


operator), que precisa de uma operação como
argumento Por
exemplo
a redução soma pode ser executada por /+
a redução multiplicação pode ser executada por /*
p p  
    p p  
    ppp
 & ë  !
3) Um conjunto de formas funcionais 
(também chamadas de funções de alta ordem) para a
construção de novas funções

As formas funcionais permitem que


programadores definam novas funções como
combinações de funções sem o uso explícito
de estruturas de controle tais como comandos
de iteração e condicionais

As funções são entidades de 1ª classe, porque


podem ser:
(passadas como parâmetros
(retornadas como resultado
(armazenadas em estruturas de dados
p p  
    pp
"
ë 
p p  
   &
 
   &
A execução
execuçãodedeprogramas
programasfuncionais é
baseada sobre
funcionais dois mecanismos
é baseada sobre dois
fundamentais: amarração
mecanismos fundamentais: e aplicação

1) Amarração é usada para associar valores a


nomes
Dados e funções podem ser usados
como valores

2) Aplicação é usada para computar novos


valores
p p  
    pp
p p  
   & 
ë 
p p  
   &
Lambda Calculus
A execução de programas
$ um cálculo simples que pode ser usado
para modelar, éprecisamente,
funcionais baseada sobre dois
mecanismos
o comportamento fundamentais:
das funções
pela definição
das semânticas de amarração e aplicação

Alonzo Church desenvolveu


Lambda Calculus em 1930 ver
gjm.lambook88
como uma teoria de funções
que oferece regras para
a manipulação de funções
de uma forma puramente sintática
O desafio de resolver todas as
questões matemáticas:
1936: Church

Todas as propostas sérias de um


modelo de computação têm o
mesmo poder, i.e, calculam as
mesmas funções ou reconhecem as
mesmas linguagens.
equivalência

6. Máquinas de Turing  p
Máquina de Turing mT
Modelo matemático do processo de
computação

Pretende alcançar um modelo


universalmente aceito!

Principal uso: demonstrar o que é ou


não computável

6. Máquinas de Turing  
Tese de Church
1- Todos os modelos razoáveis de
procedimento são equivalentes

2- Mas a mT revelou-se o modelo


mais flexível para as demonstrações
do que é ou não computável

6. Máquinas de Turing  
p p  
   
p p  
    pp
& 
p p  p' 
(   ë 
 &#

Embora Lambda Calculus tenha surgido como


um desvio da lógica matemática para prover
um fundamento para a matemática, ela tem
conduzido a ramificações consideráveis na
teoria da linguagem de programação:
1) Embora Lambda Calculus tenha poder para
representar todas as funções computáveis, a
simplicidade de sua sintaxe e sua semântica
provê um veículo excelente para o estudo do
significado de conceitos de linguagem de
programação
p p  
   
p p  
    pp
& 
p p  p' 
(   ë 
 &#

Embora Lambda Calculus tenha surgido como


um desvio da lógica matemática para prover
um fundamento para a matemática, ela tem
conduzido a ramificações consideráveis na
teoria da linguagem de programação:
2) Todas as linguagens de programação
funcional podem ser vistas como uma
variação sintática de Lambda Calculus, tal que
suas sintaxe e implementação possam ser
analisadas no contexto de Lambda Calculus
p p  
   
p p  
    pp
& 
p p  p' 
(   ë 
 &#

Embora Lambda Calculus tenha surgido como


um desvio da lógica matemática para prover
um fundamento para a matemática, ela tem
conduzido a ramificações consideráveis na
teoria da linguagem de programação:

3) Semântica denotacional, um dos primeiros


métodos de especificação formal de
linguagens, expressa suas definições usando
as funções de alta ordem de Lambda Calculus
p p  
   
p p  
    pp
&
p p  p' 
(   ë 
 &#

Lambda calculus é um cálculo simples que


modela os aspectos computacionais de
funções

O estudo de lambda calculus nos ajuda a


compreender os elementos da programação
funcional e o entendimento da semântica das
linguagens de programação funcional,
independentemente, dos detalhes de sintaxe
de uma linguagem particular de programação
funcional
p p  
   
p p  p' 
(    p p 
 
   
& &#
!
Há 3 espécies de expressões em lambda calculus: ë 

e1 um simples identificador tal como Ex: função


quadrado
Ñ, ou uma constante tal como
definida como
e2 uma definição de função, com a OÑÑÑ
forma OÑ, que representa a expressão  com Ñ
entendida como uma variável amarrada. A expressão
 representa o corpo da função e Ñ o argumento da
função. A expressão  pode conter qualquer das três
formas de expressão lambda: e1, e2 ou e3.
e3 uma aplicação de função com a forma (e1 e2), que
representa a expressão e1 aplicada a expressão e2.
Ex
função quadrado aplicada ao valor p OÑÑÑp
p p  
    pp
p p  
   &
p p  p' 
(   &#
"
ë 
Parênteses podem ser omitidos de p e
de OÑ

Na ausência de parênteses, na aplicação de


função, a precedência de associação é da
esquerda para a direita

Assim, p significa p 

aplicação de função tem precedência maior


que definição de função

Exemplo: OÑsignifica OÑ


p p  
    pp
p p  
   &
p p  p' 
(   &#

ë 
Uma variável que aparece numa definição de função F
é dita livre em F se ela não é amarrada em F

Variáveis amarradas são como parâmetros formais


numa definição de rotina e agem como variáveis
locais

Variáveis livres são como variáveis não locais que


serão amarradas em um nível mais externo

Por ex, a definição de função OÑÑ define a função k-


ésima potência
com x como uma variável amarrada e
k como uma variável livre
p p  
    pp
p p  
   &
p p  p' 
(   &#
p
ë 

A sintaxe para expressões lambda


mostra que
a aplicação de função utiliza
a forma de prefixo
sendo a notação usual ðÑ
substituída por ðÑ
p p  
    pp
p p  
   &
p p  p' 
(   &#

ë 
Implicitamente foi assumido que as funções têm um só
argumento, realmente, lambda calculus usa uma alternativa
ingênua para funções com múltiplos argumentos. Todas as
funções são reduzidas para funções de argumento único por
meio de um mecanismo conceitual chamado —  (após
o lógico Haskell B. Curry tê-la introduzido)

P/ex, podemos expressar a soma de 1 e 3,


normalmente escrito como 1+3, ou
na forma funcional, soma (1,3)
Na sintaxe de lambda calculus,
escreveríamos: soma 1 3
ou usando o operador +: + 1 3, que agrupa (+1) 3

A expressão   denota a função que adiciona  ao


argumento, no caso o valor .
p pp p
 
   
 p' 
(   &#

p p  
   & pp

Lambda calculus captura o comportamento de
funções com um conjunto de regras de
reescrita de expressões lambda

ë 
A reescrita de uma expressão modela
um
passo na computação de uma função

Para aplicar uma função a um argumento, nós


reescrevemos a definição da função,
substituindo ocorrências da variável amarrada
pelo argumento para o qual a função está
sendo aplicada
p p  
    pp

ë 
p p  
   &
p p  
   &
A seguir,
execuçãofaremos:
de programas
funcionais é baseada sobre dois
mecanismos
uma fundamentais:
revisão dos elementos básicos da
programação funcional, usando a
sintaxe de Haskell
p p  
    pp

p p p)
*  €€€  ›  
  ë ›

 
p p  
   &
Supondo o seguinte trecho em Java, baseado em
atribuição de variável, para soma de 1 a 100
A execução de programas funcionais é baseada
› ` 

` 
sobre
ð`› mecanismos fundamentais:
dois ›
 ›
 ›  muda 100
` 
`  › vezes

Em Haskell, a codificação para soma de 1 a 100


- está baseada na função sum e na idéia de lista
implícita
- o método de programação é aplicação de função

   Especificada uma aplicação


 
@  de sum ao argumento lista
de 100 elementos.
p p  
    pp

p p p)
*  €€€  ›  
  ë ›

 
p p  
   &
Em Haskell, notar que   
o código:  
@ 

- está baseado na função sum e na idéia de lista


implícita
- o método de programação é aplicação de função

Conseqüências da abordagem funcional:

Uma vez estabelecido o valor de s1_100


- tem um tipo definido (pode ser implícito)
- o valor não pode ser mudado
- o valor pode ser usado como argumento de funções
p p  
    pp

p p p)
*  €€€  ›  
  ë ›

 
p p  
   &

Uma pergunta que surge é

SERÁ QUE $ POSSÍVEL PROGRAMAR ?

(SEM ITERAÇÕES

(SEM EFEITOS COLATERAIS

(SEM MUDAR O VALOR DE VARIÁVEIS


p p  
    pp
!
€€€  ›  
  ë ›

 
p
p ppp)
* 
 
   &

Expressões
A execução de programas funcionais é baseada
Em Haskell,
sobre as expressões
dois mecanismos são especificadas
fundamentais:
com os seguintes símbolos ou construções:

(Constantes
(Operadores
(Aplicação de funções
(Parênteses ( )
p p  
    pp
"
€€€  ›  
  ë ›

 
p
p ppp)
* 
 
   &
(Constantes
Expressões (Operadores
(Aplicação de funções
A execução de programas funcionais
é baseada
(Parênteses ( )
sobre dois mecanismos fundamentais:
Constantes:
True
2009
Aplicação de Funções:
28876543212125
12.589
primo 53
¶b·
seno 30
´cadeiaµ
[4,8,9]
p p  
    pp

€€€  ›  
  ë ›

 
p
p ppp)
* 
 
   &

Operadores
A execução de programas funcionais é baseada
sobre
. dois mecanismos fundamentais:
composição de funções
*, /, ^ produto, divisão, potência
+, - adição, subtração
:, ++ composição de listas, concatenação

==, /=, <=, ... igual, diferente, comparação


&& E
|| OU
p p  
    pp
p
p p p)
*  Definições
€€€  ›  
  ë ›

 
p p  
   &
Programador pode definir constantes e funções

-- P
A execução de programas funcionais é baseada
›
 
sobre dois mecanismos fundamentais:
-- @``
›@`
p›
significa em lambda calculus ´ð ›@`
Op›µ
Uma aplicação: ´›@` µ
-- á `
 
›p
significa em lambda calculus ´ ð  
O›pµ

Uma aplicação: ´   µ
p p  
    pp

€€€  ›  
  ë ›

 
p
p ppp)
* 
 
   &

Tipos básicos
A execução de programas funcionais é baseada
Bool dois mecanismos
sobre booleano fundamentais:
Char caracter
Int inteiro de 32 bits
Integer inteiro sem limite no tamanho.
Float ponto flutuante
Double precisão dupla
p p  
    p p p)
*  pp

Tipos em Haskell
p p  
   &
ë 
€€€  ›  
   ›  
Toda expressão deve ter um tipo associado
Tipos
A podem
execução deser explícitos
programas ou inferidos
funcionais é baseada
sobre dois mecanismos
@` fundamentais:
->` ->` 
@Ñ
Ñ 
@p` ->` 
@p
@p
›@`` ->` 
›@`
p›
 ` ->` 
 
›p
p p  
    p p p)
*  pp

ë 
pTuplas
p  
   &
€€€  ›  
   ›  

Haskell permite composição de tipos:


A
execução
 de--
programas funcionais
›é›`
baseada
sobre dois mecanismos
 !" fundamentais:
#``$ 

Em geral, (A, B) representa um tipo, cujo


primeiro membro é do tipo A e o
segundo membro é do tipo B.

O emprego de tuplas é uma estratégia para


permitir o retorno de mais de um valor da
função, que aparece no formato de tupla.
p p  
    p p p)
*  pp

ëtipos:

Tuplas Haskell permite composição de
p p  
   &
  --  › ›`
 !" #``$ 
A execução de programas funcionais é baseada
sobre
Em dois
geral, (A,mecanismos fundamentais:
B) representa um tipo, cujo primeiro
membro é do tipo A e o segundo membro é do tipo B.

Exemplo de uma função que devolve os dois valores:


a soma e a subtração de dois argumentos de entrada.

`@    ->  


`@    
  - 

EX. de P>`@  p


execução:  -
€€€  ›  
   ›  
p p  
    p p p)
*  pp

ë 
pp  
   &
€€€  ›  
   ›  

Conjunto de definições de funções


þ  -> -- › 
þ  
  --  @  @ `

` ` -> 
` ` 
p
`   -> 
`   
þ ` ` 
p p  
    p p p)
*  pp
ë 
pFunções Uma função é um mapeamento de
p  
   &
valores de um tipo em outro tipo

`#``->#``
›››!" ->#``

  -> 


Ñ
Ñ 

€€€  ›  


   ›  
p p  
   
 
    p p p)
*  pp
 !
ë 
pFunções
p  
   &
Aplicação de funções em Haskell

Matemática Haskell
ðÑ ðÑ
ðÑ ðÑ
ðÑ ðÑ
ðÑ ðÑ
ðÑmultiplica ðÑ
ð    ð   

precedência de aplicação de funções é maior


€€€  ›  
   ›  
p p  
    p p p)
*  pp
"
Voltando ao exemplo em Tuplas ë 
p p  
   &
`@    
  - 
aparece um único parâmetro, a tupla, que
tem dois valores
A execução encapsulados.
de programas funcionais é baseada
sobre dois mecanismos fundamentais:
Função Currificada

Uma variação é transformar a versão acima


em uma versão currificada, reescrevendo
`@     como:

`@   -> ->  


`@    
  - 
 
   ›  ›    ›   ›
p p  
    p p p)
*  pp

ë
Um
exemplo mais abrangente de função currificada
p p  
   &
ð `›ð›  Ñ
Ñ   
ð›ð›  Ñ
Ñ   
A execuçãopermitidas
Alternativas de programas funcionais é baseada
para execução:
sobre dois mecanismos fundamentais:
§ › >ð›ð›   %
&
§ › >ð›ð›   %
&
§ › >ð›ð›   %
&
§ › >ð›ð›   %
&
§ › >ð›ð›   %
&
§ › >ð `›ð›   %
&
   
    
 
  
p p  
    p p p)
*  pp
p
ë 
Função Currificada Observações importantes
p p  
   &
ð `›ð›  Ñ
Ñ   
ð›ð›  Ñ
Ñ   
A execução de programas funcionais é baseada
Uma função de n parâmetros pode ser contraída em
sobre dois mecanismos fundamentais:
uma função de um parâmetro.

O modo como os passos podem ocorrer nas várias


alternativas de execuções vistas foi possível devido
ao fato dos parâmetros estarem livres entre si.

Vimos a transformação abstrata de várias somas de


acordo com a associatividade da esquerda para a
direita.

 
   ›  ›    ›   ›
p p  
    p p p)
*  pp

Função Currificada Observações ë 
importantes
p p  
   &
ð `›ð›  Ñ
Ñ   
ð›ð›  Ñ
Ñ   
A execução
Essa abstração, de programas funcionais é baseada
sobre
seguindodois
a mecanismos
&
fundamentais:
§ › >ð›ð›   %
associatividade § › >ð›ð›   %
esq./dir., em que o &
valor 3 foi o primeiro § › >ð›ð›   %
a ser avaliado e o valor &
6 o último a ser § › >ð›ð›   %
avaliado, reforça o &
conceito de avaliação § › >ð›ð›   %
preguiçosa, em que &
§ › >ð `›ð›   %
nada é calculado até
&
que seja efetivamente
necessário.
   
    
 
  
p p  
    p p p)
*  pp

ë 
Função Currificada Observações importantes
p p  
   &
ð `›ð›  Ñ
Ñ   
ð›ð›  Ñ
Ñ   
A execução de programas funcionais é baseada
§ › >ð›ð›   %
sobre
Em outrasdois mecanismos
palavras, & fundamentais:
na avaliação preguiçosa, § › >ð›ð›   %
transformações abstratas &
intermediárias foram § › >ð›ð›   %
adiadas, até que a &
disponibilidade dos § › >ð›ð›   %
&
termos numéricos fosse
§ › >ð›ð›   %
necessária na expressão. &
§ › >ð `›ð›   %
&

   
    
 
  
p p  
    p p p)
*  pp

ë 
Função Currificada Observações importantes
p p  
   &
ð `›ð›  Ñ
Ñ   
ð›ð›  Ñ
Ñ   
A execução de programas funcionais é baseada
A associatividade à esquerda é observada e para o
sobre dois mecanismos fundamentais:
caso de 4 argumentos em uma função f, note que:

f a b c d = ( f a ) b c d = ( ( f a ) b ) c d = ( ( ( f a ) b ) c) d

Uma generalização para n argumentos é inferida.

Em outras palavras, toda função é aplicada ao seu


primeiro argumento, à sua direita, depois, o resultado
desta expressão avaliada é aplicada ao segundo
argumento, e, assim, sucessivamente, até o último
argumento na função.
   
    
 
  
p p  
    p p p)
*  pp

ë 
Função Currificada Observações importantes
p p  
   &
ð `›ð›  Ñ
Ñ   
ð›ð›  Ñ
Ñ   
A execução de programas funcionais é baseada
Finalmente, a função ð›ð›  tem uma
sobre dois mecanismos fundamentais:
equivalente em uma notação prefixada, pelas razões
anteriores, que, em Haskell, pode ser escrita, como a
seguir:

ð›ðpÑ
   Ñ

Execução para ð›ðp %na pag. seguinte

   
    
 
  
p p  
    p p p)
*  pp

ë 
Função Currificada
p p  
   &
Execução da função equivalente em uma notação
préfixa

ð›ðpÑ
   Ñ
A execução de programas funcionais é baseada
sobre dois mecanismos fundamentais:
§ › >ð›ðp %
&
§ › >ð›ðp %
&

   
    
 
  
p p  
   
 
    p p p)
*  pp

Recursão
   
    
 
  

A indução matemática é apropriada


para olhar a recursão

A indução matemática proporciona


uma propagação típica
da recursividade

Indução Matemática é
uma definição generalizada
para um conjunto de objetos
com uma propriedade comum
p p  
    p p p)
*  pppp!

Indução é !
uma definição generalizada
Recursão
para um conjunto de objetos
com uma propriedade comum
Deve-se conhecer o caso trivial,
geralmente, para n=0, n=1,
que são os valores²base ou triviais

O passo seguinte é demonstrar que,


para um n genérico,
a propriedade indutiva mantém-se desde n-1
Então, para o termo n
essa propriedade indutiva permanece válida,
considerando que em n-1 era verdadeira
   
    
 
  
p p  
    p p p)
*  p p "
Indução é
uma definição generalizada
Recursão
para um conjunto de objetos
com uma propriedade comum

O conceito dessa idéia de indução é a


base de toda a programação em Haskell,
mas esses passos matemáticos
são deixados a cargo do computador
Para esses cálculos,
uma propagação que começa de n
é construída do fim para o início,
até o caso trivial dessa regra recursiva
   
    
 
  
p p  
   
 
    p p p)
*  pp
Recursão
 
Exemplo clássico de recursão,
por meio de uma idéia indutiva

Soma dos n primeiros inteiros.

1 + 2 + 3 + ... + (n-1) + n,
representado por soma (n)

soma (5) = 1 + 2 + 3 + 4 + 5 = 15

   
    
 
  
p p  
   
 
    p p p)
*  pp
Recursão
 p
Raciocínio p/ soma dos n
primeiros inteiros 1+ 2 + 3 + 4 + ... + n
soma 1 = 1

soma 2 = (soma 1) + 2 V 


   -
soma 3 = (soma 2) + 3  `
V 
soma 4 = (soma 3) + 4   
...
soma n = (soma (n-1)) + n

então soma (n) = 1 :n=1


soma (n-1) + n : n > 1
   
    
 
  
p p  
   
 
    p p p)
*  pppp

Recursão
 

soma (n) = 1 :n=1


soma (n-1) + n : n > 1

Observa-se uma soma repetitiva entre


o último número com
a soma acumulada até o número antecessor

regra indutiva geral: soma n = soma (n-1) + n

aterramento (última ação da função): soma 1 = 1

O código em Haskell fica então, como a seguir:

soma 1 = 1
soma n = soma (n-1) + n

   
    
 
  
p p  
   
 
    p p p)
*  pp
Recursão Outro exemplo clássico de recursão é 

o fatorial de um número inteiro.

raciocínio para fatorial de n:


fatorial 0 = 1

fatorial 1 = (fatorial 0) * 1

fatorial 2 = (fatorial 1) * 2

fatorial 3 = (fatorial 2) * 3
...
fatorial n = (fatorial (n-1)) * n

então fatorial (n) = 1 :n=0


fatorial (n-1) * n : n a 1
   
    
 
  
p p  
   
 
    p p p)
*  pp
Recursão
 

fatorial (n) = 1 :n=0


fatorial (n-1) * n : n > 1

Observa-se um produto repetitivo entre o último


número com o produto até o número antecessor.

regra indutiva geral: fatorial n = fatorial (n-1) * n

aterramento (última ação da função): fatorial 0 = 1

O código em Haskell fica então, como a seguir:

fatorial 0 = 1
fatorial n = fatorial (n-1) * n
   
    
 
  
p p  
   
 
    p p p)
*  pp
 
Cuidados com a Recursão
O aterramento da função deve aparecer antes da
chamada da função recursiva geral.
— Cuidado: caso se inverta,
ocorre uma seqüência infinita de chamadas.

regra indutiva geral: fatorial n = fatorial (n-1) * n

aterramento (última ação da função): fatorial 0 = 1

O código em Haskell fica então, como a seguir:

fatorial 0 = 1
fatorial n = fatorial (n-1) * n
   
    
 
  
p p  
   
 
    p p p)
*  pp
 
Uso de guardas |
para aterramento e regra geral
Uma guarda é uma condição lógica para que a
definição da função seja executada

As guardas ð `  p


podem ser '  
Ñ`
montadas,
'  p
Ñ`p
como ao
lado: 
'`"›
Ñ`
Nessa montagem, uma função pode possuir:
m args, n guardas c/ suas respectivas expressões, e um
otherwise, que abrange as demais condições possíveis mas não
declaradas.
   
    
 
  
p p  
   
 
    p p p)
*  pp

Exemplo com e sem uso de guarda, para a
especificação de uma função que retorna quantos
múltiplos de 7 há em x (no intervalo de 0 a n):

@›((

@›(Ñ COM
@›( 
 'Ñ>
))Ñ
%

@›(
  '`"›
 @›(Ñ-(
@›(p

@›( 

@›(
 SEM
@›(

@›(%

@›((

@›(Ñ
 @(Ñ-(
   
    
 
  
p p  
   
 
    p p p)
*  pp
 !
Exemplo com e sem uso de guarda, para a
especificação de uma função que retorna quantos
múltiplos de 7 há em x (no intervalo de 0 a n):

@›( 

@›(
  @›((
 COM
@›(p
 @›(Ñ
@›( 
 'Ñ>
))Ñ
%

@›(
 '`"›
 @›(Ñ-(
@›(

@›(%
 SEM
@›((

@›(Ñ
 @(Ñ-(

Observar que há muitas linhas na definição sem o


emprego de guardas. Com guarda, a definição da
função fica contraída.
   
    
 
  
p p  
   
 
    p p p)
*  pp
 "
Exemplo com e sem uso de guarda, para a especificação de uma
função que retorna quantos múltiplos de 7 há em x (no
intervalo de 0 a n):

@›( 

@›(
  @›((
 COM
@›(p
 @›(Ñ
@›( 
 'Ñ>
))Ñ
%

@›(
 '`"›
 @›(Ñ-(
@›(

@›(%
 SEM
@›((

@›(Ñ
 @(Ñ-(
A variável x (arg) na função multi_7 fez um
casamento condicional com valores de 0 a 6,
retornando 0, enquanto que para os demais valores,
recursivamente segue na busca de mais múltiplos.
p p  
   
 
    p p p)
*  pp
 
CASAMENTO DE PADRÕES

Casamento de Padrão é
um recurso de alto nível para
a declaração das diferentes condições,
nas quais se baseiam as execuções
das diferentes ações especificadas

   
    
 
  
p p  
   
 
    p p p)
*  pp
CASAMENTO DE PADRÕES - exemplo
 p

  › 
'*' '›'Ñ' '`@

›  `› ->#`` A função 
›  ` 
* ›  ` é
definida por uma série
›  ``@
* de casos.
›  `
  Dependendo do valor,
no argumento com o
Pelo ex, vimos que há dois efeitos: qual a função é
p 1) O argumento é amarrado ao invocada, o caso
padrão quando há casamento; apropriado será
2) a ação é escolhida, baseada selecionado.
no argumento. Os casos são
verificados
seqüencialmente , do
A variável amarrada (arg) pode ser primeiro em diante.
usada no mapeamento.
   
    
 
  
p p  
   
 
    p p p)
*  pp
 
CASAMENTO DE PADRÕES

@›( 

@›(
  @›((

@›(p
 @›(Ñ
@›( 
 'Ñ>
))Ñ
%

@›(
 '`"›
 @›(Ñ-(
@›(

@›(%

@›((

@›(Ñ
 @(Ñ-(

Essa duplicação de código poderia ser evitada ? Sim.


Vamos ver exemplos interessantes de casamento de
padrão, a seguir.
   
    
 
  
p p  
   
 
    p p p)
*  pp
Exemplo didático para uso de casamento de padrões 


ðÑ 'Ñ

(
 Casamento de padrão
'

&
p (pattern matching) pode ser
visto como uma
'


 generalização de passagem
'`"›
 de parâmetro convencional.

Notação com várias O valor do parâmetro real é


condicionais na mesma usado para casar-se com
aquele que aparece na parte
linha, para a função g do parâmetro formal.
equivalente a função f
Assim o caso a ser
(
 selecionado pode variar de
Ñ&
p chamada a chamada.
Ñ

Ñ' Ñ+
(''+
&''+



   
    
 
  
p p  
   
 
    p p p)
* 
emprego de variável anônima, identificada por _ pp
 

A função h é outro exemplo "(



equivalente às funções f e g, "&
p
com o emprego de variável "

anônima, identificada por _ "


ðÑ 'Ñ

(

'

&
p EQUIVALENTES
'



'`"›


(

Ñ&
p
Ñ

Ñ' Ñ+
(''+
&''+



   
    
 
  
p p  
   
 
    p p p)
*  pp
 
ðÑ (
 "(

'Ñ

(
 Ñ&
p "&
p
'

&
p Ñ
 "

'


 Ñ' "

'`"›
 Ñ+
(''
+
&''
+



As execuções mostram que f, g e h são equivalentes:


§ › >ð(& § › >(& § › >"(&
§ › > § › > § › >
§ › >ð(& § › >(& § › >"(&
§ › >p § › >p § › >p
§ › >ð(& § › >(& § › >"(&
§ › > § › > § › >
§ › >ð(& § › >(& § › >"(&
§ › > § › > § › >
   
    
 
  
p p  
   
 
    p p p)
*  pp
ðÑ (
 "(
 

'Ñ

(
 Ñ&
p "&
p
'

&
p Ñ
 "

'


 Ñ' "

'`"›
 Ñ+
(''
+
&'' f, g e h são
Pq, as execuções,
+

 equivalentes
abaixo, ðe "
com (&
por causa da associatividade à esquerda
resultam em  ? na currificação

§ › >ð(& § › >(& § › >"(&


§ › > § › > § › >
§ › >ð(& § › >(& § › >"(&
§ › >p § › >p § › >p
§ › >ð(& § › >(& § › >"(&
§ › > § › > § › >
§ › >ð(& § › >(& § › >"(&
§ › > § › > § › >
   
    
 
  
p p  
   
 
    p p p)
*  pp

Tipos Compostos com Tuplas
Novos tipos podem ser
Exemplo: uma tupla
construídos com o uso da
contendo as estações
função  pré-definida em
climáticas
Haskell. Lembra ð em C.

! › 
› $- ›   
,`@
! › ! › ! › ! › 
ð `@  `,`@
ð `@  `
 V `` `P›@ V   `

› V `Ñ



As funções genéricas de
`` `Ñ
Ñ seleção empregaram
›@ Ñ
Ñ casamento de padrão
V `Ñ
Ñ com
var. anônima
   
    
 
  
p p  
   
 
    p p p)
*  pp
 !
Tipos Compostos com As Tuplas
funções de seleção
empregaram casamento de
Observar que: padrão com var. anônima
Cadeia empregou String,
Nomes_4 empregou Cadeia, e
f_nomes_estacao empregou Nomes_4

! › 
› $- ›   
,`@
! › ! › ! › ! › 
ð `@  `,`@
ð `@  `
 V `` `P›@ V   `

› V `Ñ


Ñ Funções genéricas,
`` `Ñ
Ñ sem assinatura,
›@ Ñ
Ñ tipo será inferido,
V `Ñ
Ñ no argumento,
na hora da aplicação
   
    
 
  
p p  
   
 
    p p p)
*  pp!
 Tipos Compostos com Tuplas "
ð `@  `
 V `` `P›@ V   `
› V `Ñ

`` `Ñ

›@ Ñ

V `Ñ

§ › >ð `@  ` Execuções


 V `` `P›@ V   ` com as
§ › >› V `ð `@  ` funções
 V ` definidas
§ › >V `ð `@  ` acima
  `
§ › >`` ```P`
`§ ›`
P`
   
    
 
  
A última execução deve-se a funções genéricas
p p  
   
 
    p p p)
*  pp!
Tipos Compostos com Tuplas
 

Novos tipos podem ser Exemplo: uma tupla


construídos com o uso da contendo campos
função  pré-definida em com tipos diferentes
Haskell. Lembra ð em C. (lembra  em
C): nome, idade, peso
e esporte favorito.
P`
` 
 
 
P` 
›  P`› 
ð-` `ð@ › P` $- ›  +› ð 

ð-` `
` `! `p%(  `›
ð@ › 
§ › .› p p(* ›

   
    
 
  
p p  
   
 
    p p p)
*  pp!
Tipos Compostos com Tuplas
 p

Observar que ð-` ` e ð@ › são


Peso empregou Float funções constantes,
Idade empregou Int que iniciam
Pessoa empregou um tupla c/ conteúdos às suas
String, Idade, Peso e String tuplas.

P`
` 
 
 
P` 
›  P`› 
ð-` `ð@ › P` $- ›  +› ð 

ð-` `
` `! `p%(  `›
ð@ › 
§ › .› p p(* ›

   
    
 
  
p pTipos
 
   
 
   
Compostos com Tuplasp p p)
*  pp!
 
Funções que extraem ou relacionam partes de uma tupla são
especificadas usando casamento de padrões, realizado, pela
seleção do campo desejado na tupla de 4, de modo que a mesma
tenha um tipo compatível com o que foi definido nesta função.
ð-` `ð@ › P` $- ›  +› ð 
ð-` `
` `! `p%(  `›
ð@ › 
§ › .› p p(* ›

 `@P` ->› 


› P` ->  assinaturas
`P` ->P`
`P` ->› 
 `@ ›

›  ›
› mapeamentos
` ›

` ›

   
    
 
  
 
    p Execuções
p p  
    p p)
* compas
p!
Tipos Compostos com Tuplas novas funções
 

ð-` `ð@ › P` $- ›  +› ð 


ð-` `
` `! `p%(  `›
ð@ › 
§ › .› p p(* ›

 `@P` ->›   `@ ›



› P` ->  ›  ›

`P` ->P` ` ›

`P` ->›  ` ›


§ › >ð-` ` § › >`ð@ ›
` `! `p%(  `› p(
§ › >ð@ › § › >› ð-` `
§ › .› p p(* › p
§ › > `@ð-` ` § › >`ð@ ›
` `! ` * ›

§ › >`.›P `p (  ð


ð
   
    
 
  
p p  
   
Listas Lembrando p p p)
*  pp!

ë 
Lista é uma estrutura de dados que representa uma
p p  
   &
coleção de objetos homogêneos em seqüência
A execução de programas funcionais é baseada
Lista permite que os seus elementos sejam
sobre dois mecanismos fundamentais:
consultados, alterados, incluídos em uma posição
desejada, ou removidos.

O acesso a um elemento da lista para qualquer


operação acima, conta sempre com o seu cabeçalho.

A partir do cabeçalho, os elementos podem ser


percorridos seqüencialmente até o alcance desejado.

As vezes, como forma de melhorar o desempenho,


pode-se utilizar outros apontadores, além do
cabeçalho, o corrente (último acessado), anterior,
posterior e o último.
p p  
   
Listas Lembrando p p p)
*  pp!

ë 
Em
p p Haskell, a lista é considerada como tendo duas
 
   &
partes: a cabeça (head) e o rabo (tail).
A execução de programas funcionais é baseada
A cabeça da lista é sempre o primeiro elemento.
sobre dois mecanismos fundamentais:
Por meio desse primeiro elemento é feito o acesso
aos elementos restantes da lista.

   - se esses são os elementos de uma lista,


a cabeça é o elemento , o primeiro da lista.

A notação de listas é uma seqüência de elementos,


separados por vírgula e delimitados por [ ].

Uma lista pode não conter elementos, assim, a lista


é considerada vazia [ ].
Exemplos na página seguinte.
p p  
    p p p)
*  pp!

ë 
Listas Ex. de listas com elementos homogêneos
p p  
   &
. !" --›   
. 
/Ñ0/ 000/ 0
 ›` --› › ›`
 ›`
( p%
#`` `#``$-›  `` `
#`` `
 * *
*  !" $-›  
* 
0Ñ0 0000
.› !" $-› › 
.› 
§ › / 00Ñ00 000

   
    
 
  
p p  
    p p p)
*  pp!
Principais funções pré-definidas para listas
ë 
p p  
   &
Operador 
 inclui um elemento no início da lista
P> p
 p
P>p 
p 

Para construir uma lista, basta simplesmente usar o


operador : e a lista inicialmente vazia [ ]

P>p 
p 

   
    
 
  
p p  
    p p p)
*  pp!
!
ë 
Tratando lista e o operador :

Todas as funções que tratam listas exercem


uma ação recursiva sobre ela própria.

Em cada passo n,
é invocada uma chamada ao sucessor n-1, e
esta sucessão de passos
é feita com o uso do operador :
que opera sobre o argumento lista,
separando
sua cabeça do seu tail (resto)
   
    
 
  
p p  
    p p p)
*  pp
""
ë 
Notas para o caso geral de funções recursivas
complementadas para o caso de listas

1- Enquanto a chamada à função não encontrar a sua


definição de parada (aterramento), ela segue
empilhando as instâncias pendentes em uma pilha
virtual de chamadas sobre tal função.

2- No momento em que a função encontra um


critério de parada (aterramento), ela é considerada
bem sucedida e com um valor instanciado.
A partir desse ponto, vai sucedendo-se o
desempilhamento de cada chamada pendente,
com o valor retornado, sendo empregado no
ponto da expressão em que houve a chamada.
   
    
 
  
p p  
    p p p)
*  pp
"
ë 
Notas para o caso geral de funções recursivas
complementadas para o caso de listas

3- A cada chamada recursiva, há uma nova instância


de ativação, e um casamento de padrão é definido
para o argumento da função.
Tais argumentos definem o padrão de como deve
se dar o casamento.

Como existe apenas um operador intrínseco à


lista, o separador : causa,
no argumento lista, a sua separação,
em duas partes: a sua cabeça, na esquerda, e uma
nova sublista (tail), na direita.

   
    
 
  
p p  
    p p p)
*  pp
"p
ë 
Notas para o caso geral de funções recursivas
complementadas para o caso de listas

4- A ação de separar a cabeça da lista do tail (resto) é


também conhecida pelos termos: escalpelar ou
decapitar a lista.
Esta separação da cabeça da lista faz parte de
todos os procedimentos recursivos, a fim de que
se possa acessar qualquer outro elemento da
lista, no momento que chegue a sua vez de ser a
cabeça da lista.

   
    
 
  
p p  
    p p p)
*  p pp"
p
"
ë 
Validação de uma estrutura do tipo lista

As listas autodefinem-se com o conceito clássico


de listas com os seguintes axiomas:

1- Uma lista vazia é uma lista

2- Uma sublista também é uma lista

Estas definições são recorrentes e validam se uma


estrutura é do tipo lista.

A definição de que uma sublista é uma lista,


depende da definição primária ou base,
de que uma lista vazia é uma lista.

   
    
 
  
p p  
    p p p)
*  p pp"
p
"
ë 
Reescrevendo em Haskell as seguintes definições:

1- Uma lista vazia é uma lista

2- Uma sublista também é uma lista

› 
*-- ð `
›  Ñ
› Ñ-- ð `p

A variável , neste caso, é a cabeça da lista, e,


quanto a Ñ, representa o corpo da lista.

A função 1 utiliza um padrão que casa somente


com a lista vazia, que é o final da recursão, depois
de todos os elementos terem sido decapitados, na
condição de cabeça da lista.
   
    
 
  
p p  
    p p p)
*  p pp"
p
"
ë 
Reescrevendo em Haskell as seguintes definições:

1- Uma lista vazia é uma lista

2- Uma sublista também é uma lista

› 
*-- ð `
›  Ñ
› Ñ-- ð `p

A função 2 casa com qualquer estrutura que use o


operador  : , quer dizer,
qualquer lista de no mínimo um elemento.

Por exemplo, a lista [1,2,3,4] pode ser reescrita


pela expressão 1:(2:(3:(4:[]))), e, a partir desta, os
possíveis casamentos de padrão ocorrem.
   
    
 
  
p p  
    p p p)
*  pp
Execuções de aplicações, empregando › "
ë 
› 
*-- ð `
›  Ñ
› Ñ-- ð `p

§ › >› p 


*
§ › >› / 0
*
§ › >› / 0p tipos
1222$ ! `› ð›   Œ
  ,@ !" 
1Ñ›` › / 0p
§ › >› p%&
1222$ ! `› ð›   tipos
  ,@   Œ
1Ñ›` › p%&
   
    
 
  
p p  
    p p p)
* 
Função que devolve o comprimento de uma lista p p 
"
ë 
p1-pO 
   &
comprimento da lista vazia é zero

2- O comprimento de uma lista (a:x) é dada por


1 + o comprimento da sublista x

3- a variável a é a cabeça da lista e x representa o


corpo (resto) da lista

`@`
 -- ð `
`@` Ñ
 `@`Ñ$- ð `p

   
    
 
  
p p  
    p p p)
*  p p "
Função que devolve o comprimento de uma lista

`@`
 --ð `
`@` Ñ
 `@`Ñ$-ð `p

A função 2 define a recursão, em que a cada passo, a


cabeça da lista é separada, é somado 1 e novamente
chamada `@` com o novo tail (resto) obtido da
lista, que novamente, na nova chamada vai ter sua
cabeça separada, somado +1 e resubmetido o novo
tail da lista.

A função 1 faz parar a recursão

a variável é a cabeça da lista e


Ñ representa o tail (resto) da lista
   
    
 
  
p p  
    p p p)
*  pp
Função que obtém os ›@›` elementos de 1 "!
ë 
lista
Construída com uma estratégia que utiliza
casamento de padrão
possui duas condições
›@›` 
 de parada e uma regra
›@›`
 geral recursiva.
›@›`  Ñ
 ›@›` -Ñ

Na regra geral , acontecem n recursões, cada uma


tirando uma cabeça, para formar a lista resultante.
§ › >›@›`pp
p Na volta da recursão,
§ › >›@›`pp  concatenando cada
p  cabeça com a sublista
§ › >›@›`( retornada.

   
    
 
  
p p  
    p p p)
*  pp
Função que verifica se um objeto   à lista "
ë 
 
 
  Ñ'

 
*
'`"›
 Ñ

A recursão prossegue até que:


1) a lista tenha se resumido a uma lista vazia [ ],
devido a decapitação em cada passo da sublista de
entrada, retornando False;
2)o objeto seja encontrado na lista, retornando True.

§ › > p 
*
§ › >  p 
 
§ › > 
 
   
    
 
  
p p  
    p p p)
* 
Função que ›  um objeto na lista, sem pp

repetições, i.e, se já existir, então, não insere.
ë 

Para que esse critério seja seguido, o objeto é inserido


no final da lista, para que possam ser verificados
todos os elementos da lista.

› 

›  Ñ'

 
 Ñ
'`"›
 › Ñ
A recursão prossegue até que:
1) a lista tenha se resumido a uma lista vazia [ ], quando
retorna , uma lista com um objeto, o argumento .
2) o argumento  coincida com uma cabeça de uma sublista,
retornando então a lista resultante da concatenação de com
a sublista Ñ.
3)Em todas as voltas,
cada cabeça volta a fazer parte da lista,
pela concatenação com a lista retornada da chamada.
   
    
 
  
p p  
    p p p)
* 
Testando a função que ›  um objeto na lista, p p 
p
sem repetições, i.e, se já existir, então, nãoëinsere.


Para que esse critério seja seguido, o objeto é inserido


no final da lista, para que possam ser verificados
todos os elementos da lista.

› 

›  Ñ'

 
 Ñ
'`"›
 › Ñ

§ › >› p 
p 
§ › >› pp 
p 
§ › >› p 
p 
   
    
 
  
pFunção
p  
   
que devolve o elemento de maior p p p)
* 
valor pp

ë 
São apresentadas três versões equivalentes

@ ›` 

@ ›` Ñ
›ð >@ ›`Ñ Decapita
duas
"  cabeças,
@ ›`Ñ 1º e 2º
elementos
@ ›`p 
 e
@ ›`p  Ñ' > 
@ ›`p Ñ
'`"›
@ ›`p Ñ

@ ›`  

@ ›`  Ñ' >@ ›` Ñ

'`"›
@ ›` Ñ

   
    
 
  
pFunção
p  
   
que ` uma lista p p p)
*  pp

ë 
São empregadas duas funções:
@ ` devolve o menor elemento de uma lista;
p@`V@ `, devolve uma lista sem o menor
@ ` 

@ ` '  @ `

'`"›
@ `

@`V@ ` 

@`V@ ` ' 

@ ` 



'`"›
 @`V@ `

` › 



` ›  
 
` › 

@ `` › @`V@ `
   
    
 
  
p p  
    p p p)
*  p p 
Algumas funções pré-definidas para listas
ë 
pOperador
p  
   &

comparar duas listas

P>p 

p 
*

Além de mostrar que é possível comparar duas listas,


vemos que as duas formas de representar uma lista
são equivalentes.

   
    
 
  
p p  
    p p p)
*  pp
Principais funções pré-definidas para listas 
ë 
pp "
 
   &
- comprimento de uma lista

Lista vazia  tem comprimento zero.

Lista  Ñ é dada por 1 mais o comprimento da


sublista Ñ, que também é uma lista.

P> "p( 




   
    
 
  
p p  
    p p p)
*  pp
Principais funções pré-definidas para listas 
p p-  
   &
concatena duas listas

P>p(  %&


p( %&

"  ² primeiro elemento cabeça da lista


P>" p( 
p

  ² último elemento da lista


P> p( 

   
    
 
  
p p  
    p p p)
*  pp
Principais funções pré-definidas para listas 
ë 
p p› 
   &
 ² devolve uma lista sem o primeiro elemento

P> ›p( 


( 

› › ² lista sem o último elemento


P>› ›p( 
p( 

 ² verifica se a lista está ou não vazia


P> p( 
 

P> 
€€€  ›  
   ›  
*
p p  
    p p p)
*  p p !

Principais funções pré-definidas para listas


ë 

p p  
   &
V ² devolve o reverso da lista

P>Vp( 
 (p

  ² pega os n primeiros elementos da lista


P>  p( 
p( 

` ² apaga os n primeiros elementos da lista


P>`pp( 
 

   
    
 
  

Você também pode gostar