zequita15 Posted October 8, 2016 at 02:25 PM Report #599464 Posted October 8, 2016 at 02:25 PM Boa tarde pessoal! Entrei este ano para a Uni e estou a ter uns certos problemas com Programação funcional. Não consigo perceber nada daquilo por mais que estude. Já vi tutoriais, resolvi exercícios mas estou sempre empancado, por mais que estude sinto que nunca saio do sítio. À uns anos aprendi a programar um pouco em C, VB, etc e não senti grandes dificuldades, até tive um excelente aproveitamento. Com Haskell tem sido diferente. Bem, criei este tópico para que todos os iniciantes postem as suas pequenas dúvidas de forma a nos ajudarmos uns aos outros. Aqui vai a minha: Ex.defina a função: multiplo -> testa se o número inteiro m é multiplo de n. A minha solução: multiplo :: (Int,Int)-> Bool multiplo (m,n) = if m mod n==0 then True else False qual é o problema mesmo? Já tentei simplificar, retornado o valor de 0 caso não seja multiplo e 1 caso seja (mudando em cima para Int) mesmo assim não dá. Já agora, caso quisesse colocar uma mensagem do tipo "e inteiro" como fazia? Obrigado a todos os que me puderem ajudar Cumps!
pwseo Posted October 8, 2016 at 05:01 PM Report #599465 Posted October 8, 2016 at 05:01 PM @Hugo.mls93, O teu problema é que a função mod só pode ser utilizada em notação infixa se a utilizares na forma x `mod` y (caso contrário terá que ser mod x y). Isto é daquelas coisas que se aprende desde cedo em Haskell: funções com 2 argumentos podem ser utilizadas como operadores binários se forem escritas entre `` (atenção: não são apóstrofos mas sim acentos graves). Relativamente ao teu código propriamente dito (corrigido), ainda pode ser muito simplificado. multiplo :: Int -> Int -> Bool multiplo m n = m `mod` n == 0 -- alternativamente, podia ter escrito mod na sua forma prefixa -- multiplo m n = mod m n == 0 Como vens de C, provavelmente ainda estás pouco habituado a pensar em Haskell, mas aqui vai na mesma: Os argumentos não precisam de ser envolvidos num tuplo (como tinhas (Int, Int)), isso tira-te flexibilidade a longo prazo Nunca se deve verificar uma expressão booleana e devolver True se ela for verdadeira ou False se ela for falsa. Basta devolver o resultado da própria expressão. Depois, falaste em «simplificar» devolvendo 0 ou 1. Em que medida é isto uma simplificação? A tua função tem como objectivo responder a uma pergunta: um determinado número m é múltiplo de n? A resposta é, naturalmente, booleana -- sim ou não -- e não um número inteiro. Relativamente à questão de mostrar "é inteiro" (presumo que queiras dizer antes "é múltiplo"), também não tem interesse fazer parte da tua função. Imagina que eu vou usar a tua função num programa maior, onde verifico milhares de vezes se um determinado número é múltiplo de outro; eu só quero que a tua função me devolva True ou False silenciosamente, não quero que ela imprima no ecrã do utilizador milhares de linhas com o resultado. Os programas devem ser escritos com uma separação clara entre a lógica (a tua função multiplo) e a sua apresentação (as mensagens que queres que apareçam). A partir do momento em que começas a misturá-las, vais ter muitas dores de cabeça, especialmente em Haskell. 1 Report
zequita15 Posted October 8, 2016 at 09:06 PM Author Report #599467 Posted October 8, 2016 at 09:06 PM @pwseo Muito obrigado pelas dicas!!! Já resultou! Continuo a ter certos problemas com alguns exercícios. A cada um que faço aparece-me um erro novo. Vou colocar aqui alguns dos quais tenho dúvidas. Sei que serão coisas elementares, mas é como te digo, aparece-me sempre algum erro novo. Em termos de raciocínio sinto-me "confortável" até, agora em termos de linguagem é que ainda não nada disto. Aqui vai: primUlt – que recebe uma lista e devolve um par com o primeiro e o último elemento dessa lista primUlt :: [Int]-> Int -> Int primUlt[x:xf]= (x, last [x:xf]) truncaImpar – que recebe uma lista e, se o comprimento da lista for ímpar retira-lhe o primeiro elemento, caso contrário devolve a própria lista. truncaImpar ::[Float]->Float truncaImpar[x:xf] = if mod length [x:xf] 2 == 0 then [x:xf] else [x+1:xf] max2 – que calcula o maior de dois números inteiros max2 :: Int-> Int -> Int->Bool max2 x y = If x<y then y else if x=y then False else x Sei que nesta última estou a "inventar" um bocado... mas pronto. Obrigado mais uma vez 🙂
pwseo Posted October 8, 2016 at 10:18 PM Report #599469 Posted October 8, 2016 at 10:18 PM @Hugo.mls93, O teu Haskell-fu de facto anda em baixo no que diz respeito à sintaxe. Vamos lá falar um pouco sobre o que se passa. No caso de primUlt, é-te dito que essa função recebe uma lista e devolve um par com o primeiro e último elementos da lista referida. Vejamos a assinatura que deste a esta função: primUlt :: [Int] -> Int -> Int Vou ler isto por ti: primUlt é uma função que recebe uma lista de inteiros, um inteiro e devolve um inteiro. Problema: não foi pedido nada disto. Para começar, tens ali um argumento a mais, não devolves nenhum par e, para terminar, nunca ninguém falou em Ints em lado nenhum. A assinatura correcta da função seria: primUlt :: [t] -> (t,t) Ou seja, primUlt recebe uma lista de um tipo de dados t e devolve um par do tipo (t, t). Muito mais simples, expressivo e genérico. De seguida, ainda na primUlt, tens outro erro: quando tentas fazer pattern matching de listas (onde usaste [x:xf]) não se utilizam [] mas sim (). O código final seria, portanto: primUlt :: [t] -> (t,t) primUlt (x:xs) = (x, last xs) Vou deixar-te pensar um pouco nas outras duas funções e, se quiseres, vamos resolvendo aqui os problemas que elas têm. Começa por ler bem o que é suposto elas fazerem e pensa nos tipos de dados envolvidos. Fico a aguardar a tua resposta. 1 Report
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now