Ir para o conteúdo
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

nuno35

Tipo de dados e propriedades

Mensagens Recomendadas

nuno35

Boa tarde tenho este tipo de dados que pode ter uma subarvore e tenho a seguite duvida

data HTML = Div [html] | Texto String | Negrito String 

quero fazer uma funcao que passa o o Texto para negrito e tenho este codigo que nao sei se esta correto

converter _ _ = _ _
converter Texto x = Negrito x

e tenho de fazer uma propriedade que verifique que a arvore principal é mais profunda que as subarvores e a minha duvida é como aceder as sub arvores tenho:
(supoe-se que tenho uma funcao profundidade)

prop_maior_arvore :: HTMl -> Property
prop_maior_arvore html = profundidade html > profundidade (tenho aqui a duvida de como aceder a subarvore de html)

Desde já obrigado
 

Editado por nuno35

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

Rapidamente acerca da primeira função:

  1. Os pattern matching são sensíveis à ordem, ou seja, se os argumentos corresponderem a um determinado pattern, todos os seguintes são ignorados. Nesse sentido, o teu segundo pattern nunca será executado pois o primeiro é sempre verdadeiro, quaisquer que sejam os dados passados por argumento.
  2. No teu pattern de "outros casos", _ _ = _ _ não faz sentido pois o Haskell não sabe o que devolver. _ é usado para definir "qualquer dado de entrada" e não para determinar dados de saída (não tem, sequer, qualquer sentido a nível sintáctico).

E acerca do tipo de dados:

  • O que é Div? Onde está definido html? Porquê html entre []?

Cumprimentos.

Editado por thoga31
Formatação

Knowledge is free!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nuno35

Basicamente era para ele devolver a mesma coisa que receber mas nao podendo por _ como dado de saída basicamente tenho de porigual a entrada e saída para cada caso a nao ser o que quero mudar.

no tipo de dados o Div

 é basicamente uma sub arvore do html

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31
5 horas atrás, nuno35 disse:

no tipo de dados o Div


 é basicamente uma sub arvore do html

Eu percebi isso, mas achas que está bem definido? Não te está a dar nenhum erro no GHCi?

 

5 horas atrás, nuno35 disse:

Basicamente era para ele devolver a mesma coisa que receber mas nao podendo por _ como dado de saída basicamente tenho de porigual a entrada e saída para cada caso a nao ser o que quero mudar.

Expliquei acima porque isso não faz sentido em Haskell.

Se queres ignorar todos os restantes casos, tens de explicitar os argumentos de entrada e explicitar a forma como eles são devolvidos pela função.

converter (Texto xs) = Negrito xs
converter ys = ys

 

P.S.: Sugestão adicional para podermos "ver" o HTML com que trabalhamos:

instance Show HTML where
    show (Texto xs)   = "Texto \""   ++ xs     ++ "\""
    show (Negrito xs) = "Negrito \"" ++ xs     ++ "\""
    show (Div h)      = "Div ("      ++ show h ++ ")"

 


Knowledge is free!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nuno35

Nao estou a correr o tipo de dados isto é um exercicio de um examee é assim que esta definido nao devia estar entre parenteses rectos?

Ja percebi nao posso utilizar o _ por ele nao saber o que devolver eu nao estava era encontrar ua maneira de compactar os restantes casos em vez de escrever um a um, o show eu a tinha feito.

Eu ja tentei foi usar os parenteses rectos na property 

prop_maior_arvore :: HTMl -> Property
prop_maior_arvore html = profundidade html > profundidade div[html]

mas nao esta correto

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

Atenção, o Haskell é case-sensitive, portanto div é diferente de Div. A capitalização do identificador tem, aliás, significado sintáctico em Haskell. O mesmo vale para HTML, html e (conforme tens escrito) HTMl.

De seguida, não, html entre parêntesis rectos naquele caso não me parece fazer sentido. Para conseguir correr o código, tive de definir assim:

data HTML = Div HTML | Texto String | Negrito String

Por fim, qual a definição de profundidade? Tens alguma função que te permita extrair os elementos de um HTML? Tal seria útil, porventura.


Knowledge is free!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nuno35

sim essa funcao ja é definida no enunciado basicamente se HTML for apenas Texto ou Negrito a profundidade é 1 mas é uma funcao que nao é feita por nos é apenas descrito o seu funcionamento pelo que percebi os parenteses rectos é que nao fazem sentido 

prop_maior_arvore :: HTMl -> Property
prop_maior_arvore HTML = profundidade HTML > profundidade Div HTML

 

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

Com a informação que tenho, o melhor que posso propor é isto:

maior x@(Div xs) = prof x > prof xs

 


Knowledge is free!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pwseo

@nuno35, vamos por partes.

Podemos começar pelo teu tipo de dados. Aquela variável html não está ali a fazer nada, e o compilador não sabe o que ela representa (porque na realidade não representa nada). O que tu pretendes com o construtor Div é dizer que dentro dele pode haver uma lista de elementos HTML... logo, o correcto é:

data HTML = Div [HTML]
          | Texto String
          | Negrito String

Repara que utilizo HTML tanto à esquerda como à direita do =, porque o nosso tipo de dados é, de certa forma, recursivo.

Passamos então para a implementação da typeclass Show, que o @thoga31 falou; podes utilizar a solução que te foi dada, ou então utilizar deriving Show para automatizar o processo.

 

Passemos à função converter. O teu tipo de dados HTML tem 3 construtores, como achas que deve comportar-se em cada caso? Vou resolver o primeiro por ti, e tentarás completar os restantes:

converter (Negrito x) = Negrito x
converter (Texto x)   = ...
converter (Div elems) = ...

Uma dica: no caso do construtor Div lembra-te que podes aceder aos elementos dentro dele como se fosse uma lista... logo, podes aplicar a função converter a cada um deles facilmente com um map.

 

E agora vamos à tal "propriedade". Desconheço o tipo de dados Property, mas vamos para já assumir que deveria ser um Bool.

Para conseguires testar se a profundidade de uma árvore é maior que outra, temos primeiro que ter uma forma de saber a profundidade. Vamos construir essa função:

profundidade (Div elems) = 1 + ...
profundidade _           = 0

Sabemos que a profundidade de um Div é a soma de 1 com a profundidade da maior árvore nele contida. Assumimos que os restantes construtores (Texto e Negrito) têm profundidade 0. Deixo para ti a tarefa de completar a função acima (dica: podes utilizar as funções map e maximum para solucionar o problema).

 

Uma vez tendo esta função profundidade, podemos testar facilmente a propriedade que pretendias:

prop_arvore_maior_que_subarvores x@(Div xs) = profundidade x > (maximum (map profundidade xs))

A notação x@(Div xs) permite-nos referir-nos ao argumento na sua totalidade (x) e desconstruí-lo (Div xs) em simultâneo.

 

Se leres este post e tentares completar os espaços... penso que consegues compreender o raciocínio e perceber como fazer isto por ti. Vai expondo as tuas dúvidas.

  • Voto 1

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nuno35

ok entao a funcao converter com a dica que deste parece me assim:

converter (Negrito x) = Negrito x
converter (Texto x)   = Negrito x
converter (Div elems) = map converter elems

a funçao profundidade nao é necessario mas vou faze la

profundidade (Div elems) = 1 + maximum (map profrundidade elems)
profundidade _           = 0

quanto a propriedade tenho umas certas duvidas entao tenho de receber dois argumentos a arvore e a lista de sub arvores 

prop_arvore_maior_que_subarvores x@(Div xs) = profundidade x (arvore principal) > (maximum(map profundidade xs)) (fico com uma lista da profundidade de todas as sub arvores e tiro o maximo dessa lista)


acho que ja percebi so continuo sem perceber a diferença de x@(Div xs) para x (Div xs) nao percebo bem qual é a funçao do arroba ali

Desde ja obrigado

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31
20 minutos atrás, nuno35 disse:

continuo sem perceber a diferença de x@(Div xs) para x (Div xs) nao percebo bem qual é a funçao do arroba ali

Considera o seguinte exemplo.

Tens uma lista de valores e pretendes uma função que devolva uma lista de tuplos cujo segundo elemento contenha o primeiro elemento da lista e o primeiro tenha o comprimento da lista completa. Terás qualquer coisa como isto:

foo [] = []
foo l@(x:xs) = (length l, x) : foo xs

Ao executar, terás algo assim:

Prelude> foo ['a','b','c','d']
[(4,'a'),(3,'b'),(2,'c'),(1,'d')]

Portanto, desconstrui o argumento da seguinte forma:

  • l é o nome da lista completa;
  • x é o primeiro elemento da lista;
  • xs é o resto da lista.

Isto é um único argumento, o que é completamente diferente de l (x:xs), que são 2 argumentos.

Por exemplo, quando passamos ['a','b','c','d'] à função foo, o que acontece é o seguinte:

  • l identifica a lista completa (l = ['a','b','c','d']);
  • x identifica o primeiro elemento (x = 'a');
  • xs identifica o resto da lista (xs = ['b','c','d']).

 

Aplicando ao teu caso, quando fazemos x@(Div xs), estamos a desconstruir o argumento de uma forma semelhante. Se passares à função o argumento Div [Negrito "bar"], o argumento será constituído da seguinte forma:

  • x identifica todo o argumento (x = Div [Negrito "bar"]);
  • xs só contém o que está dentro do Div (ou seja, xs = [Negrito "bar"]).

 

Cumprimentos.


Knowledge is free!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nuno35

ahh okok ja entendi é apenas um argumento mas consigo aceder a varias coisas eu ja sabia o (x:xs) desconhecia que podiamos por tambem a variavel com a lista completa incluido em apenas um argumento.

Editado por nuno35

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pwseo

@nuno35,

A tua definição de converter para parâmetros tipo Div elems está errada (dica: qual o tipo de dados de map converter elems?)

A tua questão sobre a função transposta tem alguma relação com o discutido agora? Repara que o título do tópico é incrivelmente geral, mas não é suposto os tópicos mudarem de tema frequentemente -- fica mais difícil para quem vem de fora e tenta seguir o raciocínio.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nuno35

nao, nao tem deixemos esse problema de lado

elems é uma lista de HTML e estou a aplicar a funcao converter a essa lista 

converter (Negrito x) = Negrito x
converter (Texto x)   = Negrito x
converter (Div elems) = Div (map converter elems)

 

Editado por nuno35

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pwseo

Agora sim a tua definição de converter está correcta (na resposta anterior faltava-te um Div antes de map converter elems)

Posto isto, ainda tens dúvidas em relação à tua função transposta? Se sim, porque não abrir um tópico sobre «Transposição de uma matriz» ou algo semelhante? :)

Partilhar esta mensagem


Ligação 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

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.