• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

softklin

[Resolvido] Tipos de dados e instância de classes

8 mensagens neste tópico

Boas. Estou a estudar para um exame, e tenho uma pequena dúvida aqui com com os tipos de dados. Tentei resolver um exercício de anos anteriores, que é o seguinte:

"Defina  o  tipo  de  dados  Pessoa,  considerando  que  uma  pessoa  fica caracterizada pelo nome,  idade e  lista de  filhos. Considere que a  idade é dada por um número inteiro. Note que os filhos são eles mesmos pessoas, e, por sua vez, podem ter outros  filhos  (ou  não). Torne  o  tipo  Pessoa  instância  das classes Eq  e  Ord,  sendo  a ordem dada pela idade.

Exemplos: o Pedro, de 37 anos e 3 filhos é considerado menor que o Alberto, de 50 anos

e 2 filhos. A Antónia, de 34 anos e 4 filhos é considerada igual ao Mário, de 34 anos e

sem filhos."

Tentei assim, peço que verifiquem se está a faltar alguma coisa:

-- definicao tipos de dados
type Nome = String
type Idade = Int
type ListaFilhos = [Pessoa]
data Pessoa = Nome Idade ListaFilhos

--estancia de classes ord e eq
Instance Eq Pessoa => Ord Pessoa where
    compare (Pessoa _ x _) (Pessoa _ y _)
        | x == y     = EQ
        | x > y       = GT
        | otherwise = LT

Penso que esteja certo, mas não sei se me está a escapar qq coisa. Para a instanciação, poderia ter feito apenas Data Pessoa = ... deriving Eq Ord ?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Esse data Pessoa não está bem definido. Precisa de um construtor para esse tipo:

data Pessoa = P Nome Idade ListaFilhos

Atenção que "instance" é com letra minúscula.

Depois, parece-me que tens de definir Pessoa como instância de Eq antes de a definires como instância de Ord. Para o Eq, apenas precisas de definir a função (==):

instance Eq Pessoa where
(==) (P x1 y1 z1) (P x2 y2 z2) = x1 == x2 && y1 == y2 && z1 == z2

E depois a instância de Ord fica assim:

instance Ord Pessoa where
    compare (P _ x _) (P _ y _)
        | x == y     = EQ
        | x > y       = GT
        | otherwise = LT

Se tivesses feito deriving (Eq,Ord), ele iria ordenar Pessoas pelo Nome e não pela Idade.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O deriving funcionaria para o Eq, mas para o Ord, já devia depender da forma como defines o tipo de dados.

Se colocasses a idade antes do nome, quase que funcionaria. Nesse caso a idade seria o primeiro valor a ser usado para fazer a comparação, mas quando as idades fossem iguais, ele iria comparar os outros atributos, e calcularia o resultado em função dos mesmos (no enunciado não é claro se podes fazer isso ou não).

Como disse, o enunciado não é explícito se duas pessoas com a mesma idade devem ser consideradas iguais ou não. Assumindo que sim (o que não faz muito sentido, mas é o que eu deduziria do enunciado), se definisses tu o Ord e usasses o deriving no Eq, irias ter uma incoerência entre o Eq e o Ord. Podias ter um p1>=p2 e p2<=p1 a dar True, e p1==p2 a dar False (o que é absurdo).

Resumindo, o melhor é mesmo definires tu as funções de comparação, quer para o Eq, quer para o Ord.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

@Baderous, não sabia que tinha de aplicar um construtor, não tinha isso nos meus apontamentos. Quanto à instanciação, não sabia bem se podia definir as duas logo numa só instância. Obrigado pela dicas, fiquei a perceber melhor! :D

@Rui Carlos, agora também me parece melhor definir por mim os tipos. Mas como numa aula explicaram o deriving um bocado antes do fim da mesma, não consegui acompanhar bem e tinha ficado com essa dúvida. Quanto ao enunciado, sim, 2 pessoas com idade igual são iguais neste problema (talvez para simplificar). O enunciado tinha ainda um exemplo, já agora, edito lá em cima, e fica incluído.

Obrigado a ambos! :P

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

@Rui Carlos, agora também me parece melhor definir por mim os tipos. Mas como numa aula explicaram o deriving um bocado antes do fim da mesma, não consegui acompanhar bem e tinha ficado com essa dúvida. Quanto ao enunciado, sim, 2 pessoas com idade igual são iguais neste problema (talvez para simplificar). O enunciado tinha ainda um exemplo, já agora, edito lá em cima, e fica incluído.

O deriving tenta definir automaticamente as funções. Quando tens requisitos específicos, obviamente não os poderás usar. Por exemplo, neste caso, e tendo em conta os exemplos, nem sequer podes usar o deriving para o Eq.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Então, penso que a minha instância de Eq fica também mal definida, pois 2 Pessoas apenas são iguais quando têm a mesma idade:

instance Eq Pessoa where
(==) (P _ y1 _) (P _ y2 _) = y1 == y2 

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já agora, o construtor é com os tipos "nativos", ou com os que criei?

P :: String -> Int -> [Pessoa] -> Pessoa

Será isto?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O construtor não é uma função em Haskell, é uma etiqueta que colocas para saber como é construído cada elemento do tipo que definiste. Nesse caso, o P é uma etiqueta que permite saber que um elemento do tipo Pessoa foi construído por um Nome, Idade e ListaFilhos, sendo estes tipos.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora