Jump to content
Hugo.mls93

Dúvidas de haskell para principiantes

Recommended Posts

Hugo.mls93

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!

Share this post


Link to post
Share on other sites
pwseo

@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.

  • Vote 1

Share this post


Link to post
Share on other sites
Hugo.mls93

@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 :)

Share this post


Link to post
Share on other sites
pwseo

@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.

  • Vote 1

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.