Jump to content

[Resolvido] Duvida DataTypes Haskell


skp9
 Share

Recommended Posts

Boa tarde! Gostaria que me ajudassem aqui numa pequena coisa num exercício em Haskell.

É o seguinte :

Para armazenar uma agenda de contactos telefónicos e de correio electrónico definiram-se os seguintes tipos de dados. Não existem nomes repetidos na agenda e para cada nome existe uma lista de contactos.

data Contacto = Casa Integer
             | Trab Integer
             | Tlm Integer
             | Email String

type Nome = String
type Agenda = [(Nome, [Contacto])]

Depois aparecem os seguintes exercícios:

  1. Defina a função acrescEmail :: Nome -> String -> Agenda -> Agenda que, dado um nome, um email e uma agenda, acrescenta essa informação na agenda.
  2. Defina a função verEmails :: Nome -> Agenda -> Maybe [string] que, dado um nome e uma agenda, retorna a lista dos emails associados a esse nome. Se esse nome não existir na agenda a função ao deve retornar Nothing.
  3. Defina a função consTelefs :: [Contacto] -> [integer] que, dada uma lista de contactos, retorna a lista de todos os números de telefone dessa lista (tanto telefones fixos como telemoveis).
  4. Defina a função casa :: Nome -> Agenda -> Maybe Integer que, dado um nome e uma agenda, retorna o numero de telefone de casa (caso exista).

Ora bem, a minha dúvida não está em como resolver os exercícios uma vez que tenho as resoluções mas em como testa-los. Por exemplo, em exercicios de matrizes eu definia:

type Mat a = [[a]]

e depois para testar criava uma matriz do genero:

m1 :: Mat Int
m1 = [[1,2,3],[0,4,5],[0,0,6]]

e sempre que queria testar usava essa matriz.

Eu queria saber como criar um agenda (neste caso) de modo a que dê para testar. Já tentei imensas vezes e não consegui.

E outra duvida, na alinea c), tenho a resolução:

consTelefs :: [Contacto] -> [integer]
consTelefs [] = []
consTelefs ((Casa x):ts) = x : (consTelefs ts)
consTelefs ((Trab x):ts) = x : (consTelefs ts)
consTelefs ((Tlm x):ts) = x : (consTelefs ts)
consTelefs (_:ts) = consTelefs ts

não há outra maneira de resolver o exercicio sem tantas linhas de codigo?

Edited by pwseo
Remodelação completa do post para cumprir as regras.
Link to comment
Share on other sites

skp9,

Antes de publicares o post deverias ter reparado que estavas a colocar fundo escuro e letras claras (completamente desnecessário) e, além disso, todo o código estava desformatado. Desta vez corrigi todo o teu post de modo a que os outros membros consigam lê-lo confortavelmente para te ajudar; da próxima vez não será assim.

Link to comment
Share on other sites

skp9,

Que erros obténs quando tentas criar uma Agenda? De que modo estás a tentar fazê-lo? (se não mostras, não podemos dizer-te o que estás a fazer de errado). De qualquer modo, criares uma Agenda precisas apenas de utilizar os respectivos construtores de dados. Agenda é apenas uma lista de tuplos, pelo que é simples criá-la; o problema surge nos Contactos, nesses precisas de utilizar os seus construtores:

-- Um nome sem contactos associados
pwseo :: (Nome, [Contacto])
pwseo = ("pwseo", [])

-- Um nome com 2 contactos
skp9 :: (Nome, [Contacto])
skp9 = ("skp9", [ Email "skp9@skp.xyz", Tlm 990000000 ])

-- Uma agenda:
agenda :: Agenda
agenda = [ pwseo, skp9 ]

Obviamente, isso podia ser criado directamente assim:

agenda :: Agenda
agenda = [ ("pwseo", []), ("skp9", [ Email "skp9@skp.xyz", Tlm 990000000 ]) ]

Quanto à tua segunda questão: sim, é possível utilizar menos código. No entanto, é preciso saber o que já sabes de Haskell. Já utilizaste as funções map, filter e semelhantes?

Link to comment
Share on other sites

Quanto à tua segunda questão: sim, é possível utilizar menos código. No entanto, é preciso saber o que já sabes de Haskell. Já utilizaste as funções map, filter e semelhantes?

Antes de mais peço desculpa pela forma como coloquei o post. Muito obrigado pela resposta! Quanto às funções de ordem superior, já usei o map, filter, foldr... aquelas mais básicas. É a primeira vez que estou a programar, e daí as minhas dúvidas poderem ser um bocado "básicas"

Link to comment
Share on other sites

Então vamos pensar da seguinte forma: tu queres converter uma lista de Contacto numa lista de Integer.

Para isso, precisamos de filtrar a lista excluindo os Emails e depois extrair os números, correcto?

Vamos pensar na função de extracção:

extract :: Contacto -> Integer
extract (Tlm n)  = n
extract (Trab n) = n
extract (Casa n) = n

Se reparares bem, esta função não funciona com todo o domínio de valores do tipo Contacto pois não definimos o que acontece se lhe passarmos um Email. No entanto, essa situação não se irá verificar, pelo seguinte:

isPhone :: Contacto -> Bool
isPhone (Email _) = False
isPhone _         = True

Se pensares bem, as duas funções que acabámos de definir podem ser úteis noutros contextos do teu programa; é simples imaginar situações em que precisas de extrair o número de telefone de um contacto ou determinar se esse contacto é um número de telefone ou não.

E agora vamos à função principal. Temos que a ler da direita para a esquerda: filtrar a lista aplicando isPhone e, na lista resultante, aplicar extract:

consTelefs :: [Contacto] -> [integer]
consTelefs = map extract . filter isPhone

Claro que também podes juntar tudo, mas como eu disse acima, as funções isPhone e extract (que poderias até denominar extractPhoneNumber) parecem-me demasiado úteis para as deixar como funções acessórias dentro da consTelefs:

consTelefs :: [Contacto] -> [integer]
consTelefs = map extract . filter isPhone
 where
   extract (Tlm n)  = n
   extract (Trab n) = n
   extract (Casa n) = n
   isPhone (Email _)  = False
   isPhone _          = True

Sei que o número de linhas de código desta última versão não diminuiu em relação ao teu código, mas é muito mais claro o que está a acontecer, visto que podemos ler apenas uma linha de código e compreender todo o raciocínio (os nomes extract e isPhone são auto-explicativos).

Link to comment
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
 Share

×
×
  • 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.