Atendimento
- Em qualquer altura: via correio electrónico pressionando aqui (garantir sempre que "CP" faz parte do assunto). Qualquer outro meio de contacto será considerado informal, não se sentindo a equipa docente vinculada a dar uma resposta em tempo útil.
- Durante o período de aulas: o atendimento presencial será feiro de acordo com o horário que se segue, sujeito a marcação verbal ou por email, com um mínimo de uma semana de antecedência, junto do respectivo docente:
Atendimento electrónico (FAQs)
Q1 -
Tenho dificuldades a resolver o exercício 2.8 dos apontamentos (pág. 25).
R: O diagrama representa a equação
[x,y] = [k,g].(id+id >< f)
que se quer resolver em ordem a x e y. Por absorção (etc), o lado direito fica [k,g.(id >< f)] ; pela igualdade de
eithers tem-se, de imediato,
x = k
y = g.(id >< f)
Quanto aos pontos de interrogação, comecemos pelo tipo genérico da seta vertical, que é a soma de uma identidade com um produto:
A + (B >< C) <-- id + (id >< f) -- A + (B >< D)
(repetimos A e B por estarem ligados a identidades). Como nada sabemos sobre k e g, ter-se-á
E <--- [k,g] --- A + (B >< C)
Logo, os pontos de interrogação são os tipos genéricos (paramétricos) A + (B >< D) (em cima); E (em baixo, à esquerda) e A + (B >< C) (à direita).
Q2 -
Gostaria de saber se a função (A x C + B x D) -- [π2,π2] --> C + D está bem tipada.
R: Para estar seria preciso que as duas instâncias de π2 tivessem o mesmo tipo de saída. Ora isso não acontece: tem-se
A x C -- π2 --> C num caso e
B x D -- π2 --> D no outro, ambos diferentes de C + D. Já se escrever π2 + π2 em lugar de [π2,π2] terá uma expressão funcional bem tipada.
Q3 -
Tenho uma dúvida sobre o primeiro problema do trabalho prático: a declaração do tipo de dados data Op = Op String não faz uma recursão infinita?
R: Não! O 'Op' do lado esquerdo designa o tipo de dados, enquanto o do lado direito designa um construtor. Comparando com, por exemplo, a declaração do tipo 'LTree', o primeiro 'Op' está para 'LTree' assim como o segundo está para 'Leaf'. Em Haskell, a disjunção desses "name spaces" é garantida por construção da linguagem.
Q4 -
Defini a função show' que envio em anexo tal como é pedido no exercício 3 do problema 1. Contudo, quando chamo quickCheck prop_inv no terminal, o programa fica a correr infinitamente. O que poderei estar a fazer de errado?
R: Essa tarefa pode demorar bastante tempo, até a 1 minuto será normal. Isto não quer dizer, contudo, que não seja possível melhorar o seu show'...
Q5 -
No problema 2, aparecem dois exercicios que não têm uma explicação clara do que é pedido, nomeadamente, collectLeafs e dimen. Se pudessem explicar o resultado que pretendem com estas funções agradecia.
R: A função collectLeafs retorna todas as folhas de um elemento do tipo X a b. A sua assinatura é a seguinte:
collectLeafs :: X a b -> [a]
A função dimen tem como objectivo calcular as dimensões de um elemento do tipo X Caixa Tipo, com base na suas caixas e o posicionamento relativo das últimas. A assinatura desta função é a seguinte:
dimen :: X Caixa Tipo -> (Float, Float)
Q6 - A nossa solução para show' passa nos 100 testes. No entanto, apresenta Num(a) como '(a)' e não como 'a'. Está bem assim ou é suposto aparecer
apenas um 'a', sem parênteses?
R: A vossa implementação acrescenta parênteses desnecessariamente, e portanto tem espaço para ser melhorada.
Por volta dos anos 60,
E. Dijkstra proferiu a seguinte frase, que ficou célebre:
"Testing shows the presence, not the absence of bugs". O facto de a vossa função passar nos testes
não implica a ausência de falhas ou a impossibilidade de a melhorar.
Q7 -
Relativamente ao problema 2 do TP, (1) na parte das soluções não aparecem as funções agrup_caixas e mostra_caixas. São para nós adicionarmos, correcto? (2) Que devem fazer as funções calc e caixasAndOrigin2Pict?
R: (1) Sim. (2) Quanto à função
calc: considere duas caixas a) e b). Sabendo a posição absoluta da caixa a), as suas dimensões, e a posição relativa da caixa b) em relação à caixa a), a função,
calc :: Tipo -> Origem -> (Float, Float) -> Origem, determina onde colocar a caixa b), i.e. a sua posição absoluta. (Ver também Q22 mais abaixo, sobre este assunto.) Quanto à função
caixasAndOrigin2Pict: o seu tipo é
(X Caixa Tipo, Origem) -> G.Picture. Esta função converte uma expressão em L2D (portanto uma representação textual de agregações de caixas) numa imagem.
Q8 -
No problema 4 do trabalho prático a minha função find passa por vezes nos 100 testes do quickCheck enquanto que noutras vezes fica em "ciclo infinito" e não consigo perceber porquê. O que poderei estar a fazer de errado?
R: O QuickCheck faz a geração dos casos de teste de forma aleatória e por vezes escolhe testes bastante complexos de gerar. O demorar muito tempo não quer dizer que esteja em ciclo infinito, e há uma maneira de ver isso: corra
verboseCheck prop_find em vez de
quickCheck prop_find e verá os testes que estão a ser gerados.
Q9 -
Na alínea 3(e) da ficha nº 5, fiz os diagramas de cada catamorfismo e chego às definições das funções com variáveis através da lei universal-cata e consigo perceber que realmente fazem a mesma coisa; mas não sei se era assim que era suposto resolver...
R: Não: isso
mostra, mas não
prova! O que queremos provar é que
f=g, sendo ambas catamorfismos. Logo podemos usar a lei-universal aplicada a
f ou
g, à nossa escolha, por exemplo
g = ([ i,i ])
<=> { Universal-cata }
g.in = [i, i] . (id + g)
<=> { função constante
i, fusão-+ etc, isomorfismo in/out }
g= i .[ id , g] . out
<=> { função constante
i }
g = i
Agora basta verificar se
i = f, pelo mesmo processo.
Q10 -
Faço o que diz o enunciado para instalar 'lhs2tex', cabal install lhs2tex, corre tudo bem, mas continuo sem ´lhs2tex', e.g. lhs2tex cp1718t.lhs > cp1718t.tex dá erro. (Isto em MAC OS.)
R: Se tudo correu bem na instalação, deverá existir o ficheiro executável
Library/Haskell/bin/lhs2tex. O que está a faltar é o "link" para esse ficheiro. Uma maneira simples de o fazer é definir, na shell,
alias lhs2tex='/Users/user/Library/Haskell/bin/lhs2tex'
onde
user é o nome do utilizador. Para não terem que fazer isso sempre, acrescentem essa linha ao ficheiro
.bashrc, que já deve existir na directoria principal de
user. (Este ficheiro é executado sempre que criam uma
shell ou abrem um terminal.)
Q11 -
Estou sem conseguir resolver a questão 8 do teste de 2011/12: definir um anamorfismo de naturais como um catamorfismo de listas. Tentei usar a lei universal-ana(44) mas fiquei bloqueado a meio.
R: Sim, universal-ana (naturais) é bom começo (expandindo out = [nil,cons]º ):
f = [( (id+p2). [nil,cons]º )]
== { universal-ana (naturais); álgebra in dos naturais é [0,succ] }
f = in. (id + f ) . (id+p2). [nil,cons]º
== { passando isomorfismo [nil,cons]º para o outro lado, "trocando o sinal" }
f . [nil,cons] = in. (id + f ) . (id+p2)
Aqui começa a preparação das coisas para se obter f como catamorfismo de listas. A dificuldade desta questão é que começa com um anamorfismo de naturais (
F f = id + f) e termina com um catamorfismo de listas (
F f = id + id x f). A mudança de F dá-se a partir do ponto em que se parou acima. Como sempre, as propriedades naturais não se devem ignorar, neste caso a do
p2:
f.p2 = p2.(g><f).
Continuando:
f . [nil,cons] = in. (id + f.p2)
== { f.p2 = p2.(id><f) , cf. natural-p2 }
f . [nil,cons] = in. (id + p2.(id><f))
== { natural-id; functor-+ }
f . [nil,cons] = in. (id + p2) .(id + id><f))
== { universal-cata }
f = (| in. (id + p2) |)
Q12 -
Estou a tentar resolver a questão 6 do teste de 17 de Junho de 2013: fiz os diagramas de cada catamorfismo e chego às definições das funções com variáveis através da lei universal-cata e consigo perceber que realmente fazem a mesma coisa, mas não sei se era assim que era suposto resolver...
R: Não, isso
mostra... mas não
prova! O que queremos provar é que
f=g, sendo ambas catamorfismos. Logo podemos usar a lei-universal aplicada a
f ou
g, à nossa escolha, por exemplo
f = ([ (const k), id ])
<=> { Universal-cata }
f.in = [(const k), id] . (id + f)
<=> { simplificação }
f.in = [(const k), f]
<=> { cancelamento-cata (f) }
[const k, const k].(id+f) = [(const k), f]
<=> { simplificação seguida de eq-(+) etc }
f = const k
Agora basta verificar se
const k = g, pelo mesmo processo.
Q13 -
Gostaria de perceber melhor a razão para haver uma notação funcional com variáveis ("pointfree") e outra sem elas ("pointwise") e qual se deve escolher e em que circunstâncias.
Sem variáveis os programas ficam reduzidos a expressões algébricas sobre as quais se pode raciocinar usando o Cálculo de Programas. Após os cálculos (eg. conversão da função de Fibonacci - recursiva e ineficiente -- num ciclo -- não recursivo, eficiente) converte-se o resultado final de novo para Haskell com variáveis e... "entrega-se ao cliente". Se tentar fazer o mesmo sempre com variáveis os cálculos terão que usar provas por indução matemática e serão mais longos e (para muitos) difíceis de perceber.
Q14 -
Tentei resolver o exercicio 6 do exame de 2012 mas não chego ao resultado que era pretendido. De tri f = (| in . B(id,T f) |) inferi, por cancelamento-cata, (tri f) . in = in . B(id,T f) . F(tri f). Sabendo que B(id,T f) = id + id >< T f e F (tri f) = id + id >< tri f (listas) chego a [tri f . nil, tri f . cons] = [nil, cons . (T f x tri f) ] de onde não consigo chegar ao código Haskell dado.
R: O engano está no cálculo da composição
B(id,T f) . F (tri f)
que deverá dar
id + id >< (T f . (tri f))
e não
id + (T f) >< (tri f)
Resolvido este engano, deverá ser imediato.
Q15 -
Como mostro a igualdade entre (f . id) x (g + id).i1 e f x (g + id) . ( id x i1)?
R: O problema é a falta de uns parênteses: para
f x (g + id) . ( id x i1) tipar bem é preciso colocar parênteses à esquerda da composição:
(f x (g + id)) . ( id x i1). Depois é só aplicar a lei functor-x.
NB: na nossa notação a composição tem prioridade sobre qualquer outro combinador.
Q16 -
Gostaria de saber se a função (A x C + B x D) -- [pi2,pi2] --> C + D está bem tipada.
R: Para estar era preciso que as duas instâncias de
pi2 tivessem o mesmo tipo de saída. Ora isso não acontece: tem-se
A x C -- pi2 --> C num caso e
B x D -- pi2 --> D no outro, ambos diferentes de C + D. Isto explica o que se deve fazer: escrever
pi2 + pi2 em vez de
[pi2,pi2].
Q17 -
Gostaria de saber se a função auxJoin do problema 4 do TP faz parte da valorização, uma vez que esta não se encontra no enunciado do trabalho. Aproveito ainda para perguntar o que é suposto essa função fazer.
R: auxJoin é uma função auxiliar da função
rm. O funcionamento da primeira é determinado pelo seu tipo: dada uma lista de valores do tipo
A x (B + C) e um valor do tipo
D, a função emparelha esse valor com todos os valores na lista cujo elemento à direita é do tipo
C. A função
auxJoin facilita a navegação por um sistema de ficheiros com base num caminho (análogo ao comando 'cd'), e neste sentido ajuda-nos a dividir o comando
rm em dois passos: (1) navegar até à directoria alvo; (2) remover os ficheiros desejados nessa directoria.
Q18 -
O enunciado diz: 'O objectivo final deste exercício é implementar então uma função mostra_caixas :: (L2D,Origem) -> IO ()'. Contudo, no anexo D, não aparece mostra caixas mas sim caixasAndOrigin2Pict. Temos que definir mostra_caixas?
R: Exacto, é preciso implementar no anexo D a função
mostra_caixas. A função
caixasAndOrigin2Pict (ver descrição na FAQ Q7) servirá como função auxiliar a esta.
Q19 -
Quando corro pdflatex cp1819t aparece o erro File 'xy.sty' not found. Como se resolve este problema?
R: Essa package do LaTeX, que é usada para desenhar diagramas, obtém-se instalando
https://ctan.org/pkg/xypic.
Q20 -
Ao tentar resolver a questão 5 da ficha 5 obtenho fac . in = [one,mul] . F <succ,fac>, para F f = id + f. Como é que isto me ajuda a responder à questão colocada?
R: O facto de obter
F <succ,fac> e não
F fac diz-lhe que o factorial
não é (directamente) um catamorfismo de naturais. Mais ainda: se relacionar isto com a questão 4 da ficha 7, o que acontece é que
fac está em recursividade mútua com
succ (etc, etc).
Q21 -
Quando escrevo, dentro de um bloco code, 'x^2' e corro o comando para gerar o pdf, o dito 'x ao quadrado' não aparece, mas sim uma seta entre o 'x' e o '2'. Há alguma forma de resolver isto?
R: A seta entre a base e o expoente é uma decisão do próprio
lhs2tex, que podia ser revista. Mas uma forma simples de resolver o assunto sem se ter o trabalho de alterar o
lhs2tex é a seguinte: (a) define-se
expn a b = a^b
(b) acrescenta-se, logo no início do anexo onde estão a compilar as soluções, a regra de formatação
%format (expn (a) (n)) = "{" a "}^{" n "}"
(c) Usa-se 'expn x 2' onde se usaria 'x^2', etc etc.
Q22 -
Será possível serem mais específicos sobre o que "a função, _calc :: Tipo -> Origem -> (Float, Float) -> Origem, determina onde colocar a caixa b)" quer dizer, na resposta à Q7 acima?
R: O princípio base é que a origem de um rectangulo corresponde ao seu canto inferior esquerdo: a partir disto, dados dois rectangulos (a,b),
Ht -> corresponde a posicionar a origem de b no canto superior direito de a;
Hb -> corresponde a posicionar a origem de b no canto inferior direito de a;
H -> corresponde a posicionar a origem de b
a meio do lado direito de a;
Faz-se depois um exercício análogo para V*.
Q23 -
Na questão 4-3) quando se diz “usando obrigatoriamente catamorfismos, anamorfismos ou hilomorfismos”, estes são sobre o tipo FS, ou podem ser, por exemplo, sobre listas?
R: Não têm que ser só sobre o tipo FS, mas notem que em algumas das alíneas faz mais sentido serem sobre o tipo FS.
Q24 -
Quando abro o ghci (MAC OS) e corro ex1Caixas obtenho um erro: ghc[5174:12563511] GLUT Fatal Error: internal error: NSInternalInconsistencyException, reason: nextEventMatchingMask should only be called from the Main Thread! O que quer isto dizer?
R: Esse problema é conhecido. Resolve-se usando uma flag:
ghci -fno-ghci-sandbox cp1819t. Para quem quiser saber mais, ver
1.6.1. Highlights.
Q25 -
Quando tenho fazer diagramas como é indicado no enunciado, aparece-me tudo desformatado, com eg. '@C=2cm' no PDF. Como resolvo este problema?
R: O caracter '@' é um dos caracteres reservados do lhs2tex. Devem duplicá-lo por forma a ele ser preservado e passado para o LaTeX. Assim, escrevam '@@C=2cm' e não '@C=2cm' para que a instrução seja passada intacta para o LaTeX. (Não esquecer que o lhs2tex é um pré-processador.)
A quem possa interessar
De 22 a 26 de Julho vai decorrer na UMinho o
Verão no Campus. Se alguém estiver disponível ou interessado em apoiar como monitor o módulo (Haskell) da actividade
Computação Sem Fronteiras pf diga-me (JNO).
Em dia e meio ensina-se Haskell a alunos do 10º,11º,12º anos usando problemas interessantes, relacionados com as matérias das disciplinas de Física e Matemética. Por exemplo:
- Como escrever da forma mais simples um programa em Haskell que faça a seguinte simulação do voo de regresso à terra da malograda nave Apolo XIII da NASA, em Julho de 1970?