21
Elsa Carvalho Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06) 1 Universidade da Madeira tamento de Matemática e Engenharias Âmbito das definições O âmbito de um nome introduzido por val é o contexto que se segue textualmente à sua definição. Ou seja o âmbito do nome apenas começa depois de terminada a definição. O âmbito de um nome introduzido por fun é mais lato: inclui a expressão que define a função, ou seja inclui o lado direito da definição. Isto acontece para que se possam definir funções recursivas. O âmbito de um parâmetro (definição por fun) é o da própria definição. A redefinição de nomes é possível: um nome é redefinido quando surge uma nova definição para ele num contexto em que ele já era conhecido.

Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Embed Size (px)

Citation preview

Page 1: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

1Universidade da Madeira

Departamento de Matemática e Engenharias

Âmbito das definiçõesO âmbito de um nome introduzido por val é o contexto que se segue textualmente à sua definição. Ou seja o âmbito do nome apenas começa depois de terminada a definição.

O âmbito de um nome introduzido por fun é mais lato: inclui a expressão que define a função, ou seja inclui o lado direito da definição. Isto acontece para que se possam definir funções recursivas.

O âmbito de um parâmetro (definição por fun) é o da própria definição.

A redefinição de nomes é possível: um nome é redefinido quando surge uma nova definição para ele num contexto em que ele já era conhecido.

Page 2: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

2Universidade da Madeira

Departamento de Matemática e Engenharias

Âmbito das definiçõesPara definir funções mutuamente recursivas (que estão definidas em termos uma da outra) utiliza-se a palavra chave and que introduz a definição simultânea de dois ou mais nomes.

fun f x = ... g x ...

and g y = ... f y ...

Para definições val usa-se a palavra chave and como outra forma de definir tuplos.

val V1 = E1 and V2 = E2 é equivalente a val(V1, V2) = (E1, E2)

Page 3: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

3Universidade da Madeira

Departamento de Matemática e Engenharias

Definições locaisPodemos fazer definições locais a outras definições. As primeiras serão apenas conhecidas pelas segundas.

Uma das razões para a introdução de funções auxiliares locais é o facto de sabermos que elas apenas serão utilizadas naquela outra função.

Desta forma podemos definir funções locais não robustas (que não estejam definidas para todos os valores do seu domínio) pois sabemos que quando as utilizarmos apenas utilizaremos valores do seu conjunto de partida.

Page 4: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

4Universidade da Madeira

Departamento de Matemática e Engenharias

Definições locaislocal fun potenciaLocal(b, e) = if e=0 then 1 else b*potenciaLocal(b,e-1)

in fun potencia(b, e) = if e<0 then error “potencia indefinida para

expoentes negativos”

else potenciaLocal(b, e)

end

fun quadrado n = potencia(n, 2)

Esta é uma forma de definir potencia tendo como definição local potenciaLocal, cujo âmbito se restringe à definição da 1ª função.

Page 5: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

5Universidade da Madeira

Departamento de Matemática e Engenharias

Definições locaisQualquer definição que se siga (após a palavra chave end), não ‘vê’ a função local.

A construção local é mais genericamente dada por

local DL1 DL2 ... DLn

in D1 D2 ... Dm end

em que DL1, DL2, ..., DLn, D1, D2, ..., Dm são definições (val ou fun). DL1, DL2, ..., DLn são definições locais às definições D1, D2, ..., Dm, só visíveis por estas últimas.

Em relação a DL1, ..., DLn entre si a regra normal para âmbitos aplica-se: DL2 ‘vê’ DL1, etc..

Page 6: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

6Universidade da Madeira

Departamento de Matemática e Engenharias

Definições locaisAs definições efectivamente introduzidas e que são vistas por outras introduzidas após a palavra end são D1, ..., Dm.

É possível encadear definições locais, colocando, por exemplo, no lugar de DLi ou de Dj uma definição local.

Podem-se também fazer definições locais a uma expressão, de forma a simplificar expressões mais complexas. Estas terão como âmbito a expressão a definir.

Estas definições locais são feitas dando nomes a sub-expressões e introduzindo funções temporárias nessas sub-expressões.

Esta característica torna-se importante quando utilizamos várias vezes a mesma sub-expressão dentro de uma expressão.

Page 7: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

7Universidade da Madeira

Departamento de Matemática e Engenharias

Definições locaisAssim, podemos utilizar uma tal expressão numa definição de digit

fun digit d = let val n = ord d in n>=0 codeof0 andalso n<=codeof9 end

Desta forma a expressão ord é avaliada uma só vez enquanto que o valor n é usado por duas vezes na expressão que define a função.

Se não utilizássemos esta definição local, a função digit seria definida como

fun digit d = ord d>=0 codeof0 andalso ord d<=codeof9

em que temos a expressão ord d avaliada duas vezes.

Page 8: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

8Universidade da Madeira

Departamento de Matemática e Engenharias

Definições locaisDe uma forma geral

let DL1 DL2 ... DLnin E end

é uma expressão com o mesmo valor de E, mas que usa as definições tornadas locais DL1, DL2, ..., DLn.

Page 9: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

9Universidade da Madeira

Departamento de Matemática e Engenharias

ExercíciosDiga qual o âmbito de V1 e V2 em cada uma das expressões

let val V1 = E1 O âmbito de V1 é E2 e E in let val V2 = E2 O âmbito de V2 é E

in Eend

end

let val V1 = let val V2 = E2 O âmbito de V1 é E in E1 O âmbito de V2 é E1 end

in E end

Page 10: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

10Universidade da Madeira

Departamento de Matemática e Engenharias

PolimorfismoFunções polimórficas são aquelas que podem ser aplicadas a valores de diferentes tipos.Por exemplo, a função identidade e as projecções:

fun id x = xid 5 = 5id “ola” = “ola”id (1, true, size “ola”) = id (1, true, 3) = (1, true, 3)

primeiro (1, 5) = 1segundo (false, 2) = 2

Page 11: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

11Universidade da Madeira

Departamento de Matemática e Engenharias

Não é necessário fazer várias versões de uma função se a queremos aplicar a valores de diferentes tipos. Tal coisa não acontece em linguagens como o Pascal.

De forma a ser possível designar o tipo de funções como estas, irá agora ser considerada uma extensão ao sistema de tipos. Passaremos a introduzir variáveis como , e para designar tipos genéricos (polimórficos) nos quais a igualdade pode estar ou não definida e =, = e = para designar tipos genéricos nos quais está definida a igualdade.

Polimorfismo

Page 12: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

12Universidade da Madeira

Departamento de Matemática e Engenharias

PolimorfismoAssim temos

id:

primeiro: ( x ) segundo: ( x )

isto significa que id é uma função cujo parâmetro é de um qualquer tipo e cujo resultado é do mesmo tipo que o parâmetro.

O parâmetro da função segundo é um par com componentes de quaisquer tipos e respectivamente e o resultado é um valor do tipo .

Page 13: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

13Universidade da Madeira

Departamento de Matemática e Engenharias

PolimorfismoMais alguns exemplos de funções polimórficas são a função constantemente igual a 5 e a igualdade:

fun const5 x = 5 const5: int

= : (= x =) bool

Relativamente à igualdade tal como é implementada em ML surge uma pequena restrição. Não é possível comparar valores de um qualquer tipo. Há domínios onde não é possível / eficiente e/ou não faz sentido fazer comparações: não se comparam funções, por exemplo.

Page 14: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

14Universidade da Madeira

Departamento de Matemática e Engenharias

PolimorfismoVale a pena neste ponto fazer referência ao caso da sobrecarga de identificadores.

Quando um nome é utilizado para designar duas ou mais funções diferentes, espera-se que o contexto forneça a informação adicional para que o ‘type checker’ consiga inferir qual das funções está em causa.

Assim, por exemplo, as expressões como 5 + 7 e 5.5 + 7.7 envolvem o nome ‘+’ para designar duas funções totalmente distintas: a soma de inteiros e a soma de reais. Note-se porém que esta situação não é, de forma alguma, uma situação de polimorfismo.

Page 15: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

15Universidade da Madeira

Departamento de Matemática e Engenharias

PolimorfismoFalamos em polimorfismo quando está em causa uma única função que pode ser invocada com argumentos de mais do que um tipo.

Falamos em sobrecarga de identificadores quando estão em causa funções diferentes que podem ser designadas por um mesmo nome.

Ao longo das aulas assumimos um sistema de tipos que não dá lugar a casos de sobrecarga de identificadores. Por exemplo não trabalhamos com reais e portanto o problema do ‘+’ não se põe.

Page 16: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

16Universidade da Madeira

Departamento de Matemática e Engenharias

PolimorfismoConvém no entanto notar que, se por exemplo os reais fizessem parte do sistema seríamos obrigados a qualificar expressões como x + y pois esta não fornece contexto suficiente para se saber de que soma se trata. Seria necessário qualificá-la: x + y:int (é a soma de inteiros já que y fica obrigado a ser do tipo int).

Page 17: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

17Universidade da Madeira

Departamento de Matemática e Engenharias

Funções de Ordem SuperiorA programação funcional fornece um nível de abstracção mais elevado, no qual é possível englobar os conceitos de função e de valor num único conceito. A esse nível, as funções podem ser vistas elas próprias como valores.

Para que uma função possa ser usada como qualquer outro valor é necessário que se possa:

aplicar funções a funções, i.e., permitir parâmetros do tipo função. Isto não é novidade pois devido ao operador de tipos passou a fazer sentido falar em tipos como (int int) bool, que é o tipo de todas as funções com domínio (int int) e codomínio bool; o domínio é pois um conjunto de funções.

Page 18: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

18Universidade da Madeira

Departamento de Matemática e Engenharias

Funções de Ordem Superiordar funções como resultado de funções, exº: id aplicado a dobro dá como resultado dobro que é uma função.

formar tuplos tendo funções como componentes. De facto o operador de tipos x permite escrever expressões como

(id, id dobro) cujo tipo é ( ) x (int int).

Uma função é de ordem superior quando aceita argumentos funcionais e/ou quando produz resultados funcionais. Assim, id, primeiro e segundo são funções de ordem superior.

Page 19: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

19Universidade da Madeira

Departamento de Matemática e Engenharias

Funções de Ordem SuperiorO tipo de uma função de ordem superior, envolve, tipicamente, o construtor de tipos ().

Por exemplo, (int int) (int x bool) é o tipo de uma função de ordem superior que espera receber como argumento uma função do tipo int int e retornar o tuplo (int x bool).

Por outro lado bool (int int) é o tipo de uma função de ordem superior que, quando aplicada a um valor do tipo booleano, retorna uma função do tipo (int int).

Page 20: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

20Universidade da Madeira

Departamento de Matemática e Engenharias

Funções de Ordem SuperiorOutro caso é a composição de funções. Em ML é utilizado o operador infixo ° para cômpor funções.

Para qualquer argumento x temos

(f ° g) (x) = f(g x)

Assim, a composição tem como parâmetro um par de funções e como resultado a função composta:

°: ( ) x ( ) ( )

Pode-se agora cômpor funções evitando o parâmetro, e consequentemente, utilizando val em vez de fun

val seisvezes = dobro ° triplo

Page 21: Elsa Carvalho 28 Universidade da Madeira Departamento de Matemática e Engenharias Programação em Lógica e Funcional (2000/01) (Actualizado em 2005/06)

Elsa Carvalho

Programação em Lógica e Funcional (2000/01)(Actualizado em 2005/06)

21Universidade da Madeira

Departamento de Matemática e Engenharias

Funções de Ordem SuperiorO tipo de ° é algo complicado, mas também interessante.Primeiro podemos verificar que a composição combina um par de funções e retorna ainda uma função. Assim o seu tipo há-de ser algo do género:

((T1 T2) x (T3 T4)) (T5 T6)

No entanto nem todas as funções podem ser compostas e o tipo do resultado não é independente do tipo dos argumentos.Para que f ° g faça sentido é necessário que o tipo do resultado de g coincida com o do argumento de f. Assim T4 = T1.Além disso o tipo do resultado será o mesmo que o do resultado de f e o tipo do argumento da composição será o mesmo que o do argumento de g. Assim T6 = T2 e T5 = T3. Desta forma chegamos ao resultado apresentado acima.