Recursos-LCC

Um arquivo de todo material que consegui reunir, pertinente ao curso de LCC da UM.

View on GitHub

ficha 5

Exercicio 1

Relembrem a definição de “ap” e de “swap”:

swap

Ou se quiserem em Haskell:

ap:: ((b->c), b) -> c  
ap (f,x) = f xswap:: (a,b) -> (b,a)  
swap (x,y) = (y,x)

Também será útil relembrar:

uncurry :: (a -> b -> c) -> (a,b) -> c  
uncurry f (x,y) = f x ycurry :: ((a,b) -> c) -> a -> b -> c  
curry f x y = f(x,y)

Então

flip f = curry ((uncurry f).swap)  
<=> {33 } 
ap.(flip f x id) = (uncurry f).swap 
<=> { 69}  
ap.(flip f x id) (x,y) = (uncurry f).swap (x,y) 
<=> { 70} 
ap ((flip f x id) (x,y)) = (uncurry f) (swap (x,y))  
<=> { }  
ap (flip f x, id y) =uncurry f (y,x)  
<=> { } 
flip f x y = f y x

Exercicio 2

Relembrar in=[zero,succ] sendozero: 1 -> Nat
zero x = 0 (note que zero é equivalente à função constante (const 0)) succ: Nat -> Nat succ x = x+1

Relembrem o diagrama do combinador catamorfismo de naturais e a respectiva propriedade universal: k=(|g|) <=> k.in=g.(id+k) Comecemos por desenhar o diagrama do catamorfismo de naturais para for b i

swap

Obtemos então:

for b i = (| [(const i), b] |)

E desenvolvendo

for b i = (| [(const i), b] |)
<=>{ 43 }
(for b i) . in = [(const i), b] . (id + (for b i))
<=> { def. in, 22, 1 }
(for b i) . [zero,succ] = [(const i).id, b.(for b i)]
<=> {20}
[(for b i).zero, (for b i).succ] = [(const i).id, b.(for b i)]
<=> {27}
(for b i).zero = (const i)
(for b i).succ = b.(for b i)
<=> 69, 70
(for b i) (zero ()) = (const i) ()
(for b i) (succ n) = b ((for b i) n)
<=> 72, def. succ, def. zero
for b i 0 = i
for b i (n+1) = b (for b i n)

Exercicio 3

Vamos então derivar a versão point wise a partir de

(a+) = (| [(const a), succ] |)

Temos então

(a+) = (| [(const a), succ] |)  
<=>{ 43 }  
(a+) . in = [(const a), succ] . (id + (a+))  
<=> { def. in, 22, 1 }  
(a+) . [zero,succ] = [(const a).id, succ.(a+)]  
<=> {20}  
[(a+).zero, (a+).succ] = [(const a).id, succ.(a+)]  
<=> {27}  
(a+).zero = (const a)  
(a+).succ = succ.(a+)  
<=>{ 69, 70}  
(a+) (zero ()) = (const a) ()  
(a+) (succ n) = succ ((a+) n)  
<=> {72, def. succ, def. zero}  
a+ 0 = a  
a+ (n+1) = (a+n) + 1

Exercicio 4

Vou começar por alterar o nome da função para (a#) para facilitar a escrita.
Desenhem o diagrama do catamorfismo de naturais para (a#)=(| [(const k),g] |) Reparem que para (a#) 0 temos: e para (a#) n temos: Ficamos, então

a # 0 = a  
a # (n+1) = (a # n) - 1
<=> {def. pred, def succ, def. zero, 72}
a # (zero ()) = (const a) ()  
a # (succ n) = pred (a # n)
<=>{ 69, 70}(a#).zero = (const a)  
(a #).succ = pred.(a #)
<=> {27,1}
[(a#).zero, (a#).succ] = [(const a).id, pred.(a#)]
<=> {20, 22}
(a#) . [zero,succ]= [(const a), pred] . (id + (a#))
<=> def in, F f=id+f
(a#).in = [(const a), pred] . F (a#)
<=>{ 43 }
(a#) = (| [(const a), pred] |)

k=a e g=pred

Exercicio 5

Relembre a propriedade cancelamento-cata (44) para naturais: (|g|) . in = g . (id + (|g|))

Verifique que se pode reescrever como: (|g|)= g . (id + (|g|)).out

Na aula anterior calculamos o out para naturais:

outNat 0 = i1 ()  
outNat (n+1) = i2 nou de forma equivalente:outNat 0 = i1 ()  
outNat n = i2 (n-1)

Use agora os combinadores estudados e codificados em Cp.hs para codificar (|g|)= g . (id + (|g|)).out

funcNat f = id -|- f

é só usar o combinador - -
Vamos agora a ( g )cataNat = cataNat g = g . funcNat (cataNat g) . outNat

Codifique agora: for b i =

Temos for b i=(| [(const i), b] |). Logo:

for b i = cataNat (either (const i) b)

Está agora em condições de codificar:

f = p2 . aux
where aux = for (split (succ . p1) mul) (1,1)
mul (x,y) = x*y

Vamos analisar com um diagrama qual o resultado de aux 0 ?

e aux 1

f0=1 f1=1 f2=2 f3=6 …

Notas

Tirando partidos dos catamorfismos, iremos ver como lidar com recursividade de forma muito mais estruturada e compacta em relação ao que vocês tem visto na programação. Por exemplo, iremos ver que a função,

length : [a] -> Int
length [] = 0
length (x:xs) = 1 + (len xs)

se reduz a,

length :: [a] -> Int
length = cataList (either (const 0) ((1+) . p2))

e que a função que agrega listas,

flatt :: [[a]] -> [a]
flatt [] = []
flatt (x:xs) = x ++ (flatt xs)

se reduz a,

flatt :: [[a]] -> [a]
flatt = cataList (either (const []) (uncurry (++)))

E que a função que soma todos os valores em folhas de árvores,

summ :: LTree Int -> Int
summ (Leaf x) = x
summ (Fork(x,y)) = (summ x) + (summ y)

se reduz a,

summ :: LTree Int -> Int
summ = cataLTree (either id (uncurry (+)))