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

Nazgulled

Usar o map nestas funções recursivas

9 mensagens neste tópico

Tenho aqui um par de funções recursivas as quais estou a tentar diminuir o código usando o map, mas estou com uma pequena dificuldade. Com um bocadinho de azar, isto que quero fazer não deve ser possível...

As funções recursivas são:

htmlAvisos :: [Aviso] -> Html
htmlAvisos [] = toHtml ""
htmlAvisos ((d,m,ds):r) = htmlAvisos r
             +++
             li (font ! [color "Blue"] << (show d +++ " " +++ m +++ ": ") +++ ds)

htmlFichas :: [string] -> Html
htmlFichas [] = toHtml ""
htmlFichas (f:r) = li (htmlLink f)
         +++
         htmlFichas r

E de seguida as tentativas usando o map:

htmlAvisos :: [Aviso] -> Html
htmlAvisos l = map (\(d,m,ds) -> li (font ! [color "Blue"] << (show d +++ " " +++ m +++ ": ") +++ ds)) l

htmlFichas :: [string] -> Html
htmlFichas l = map (\s -> li (htmlLink s)) l

Em ambas as funções o problema é o mesmo. O resultado do map é e não html como eu necessito. Alguma forma de resolver o problema?

P.S: Já agora, alguma forma de simplificar as minhas concatenações? É que aqueles +++ colocam as linhas de código bastante grandes... Podia dividir em várias linhas, mas queria evitar isso, prefiro assim como está se não der para melhorar as concatenações (a não ser que a linha seja mesmo muito grande).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já resolvi o problema e acabei por fazer assim no caso do htmlFichas:

htmlFichas :: [string] -> Html
htmlFichas l = foldr (+++) (toHtml "") (map f l)
  where f = (\s -> li (htmlLink s))

Mas tipo, um exemplo mais complexo:

{--
htmlHTurno :: [HoraTurno] -> Html
htmlHTurno [] = toHtml ""
htmlHTurno ((dst,hit,hft,st,dt):r) = font ! [face "Arial"] << (
                   toHtml dst +++ " feira "
                   +++
                   show hit +++ "h - " +++ show hft +++ "h, "
                   +++
                   st +++ " (" +++ dt +++ ")")
                   +++
                   br
                   +++
                   htmlHTurno r
--}

htmlHTurno :: [HoraTurno] -> Html
htmlHTurno l = foldr (+++) (toHtml "") (map f l)
  where f (dst,hit,hft,st,dt) = font ! [face "Arial"] << (
                 dst +++ " feira "
                 +++
                 (show hit) +++ "h - " +++ (show hft) +++ "h, "
                 +++
                 st +++ " (" +++ dt +++ ")")
                 +++

A função comentada é a recursiva, a outra é usando as funções foldr e map. A minha questão é, eu ganho alguma coisa em usar estas funções? É que o prof disse que valorizava o uso delas, mas eu não vejo o que é que ganho em fazer isto... É que por um lado, o código ate ficou mais confuso e nem encurtou...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

As vantagens podem estar na correcção do código, por exemplo. Ao usares um map ou um foldr tens a garantia que a recursividade termina.

Além disso, para quem estiver habituado a usar essa funções, é muito mais fácil perceber o código, pois aquilo que fazes está explícito no nome das funções. É só olhar para o nome das funções, e vê-se logo que estás a aplicar uma transformação a todos os elementos da lista (map), e que depois os estás a concatenar (foldr). Deixas de ter que perceber a parte da recursividade, e apenas tens que perceber as funções que são aplicadas sobre cada elemento, e para juntar dois elementos.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Mas em termos de percorrer a lista do inicio ao fim, usando o map e foldr não percorre mais que uma vez? Não torna isto o processo mais lento (apesar de ser algo que dificilmente se nota)?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A complexidade é a mesma, por isso a diferença nunca deverá ser grande. É claro que depende dos requisitos que tens, mas quem quer eficiência, não me parece que escolha Haskell :thumbsup:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Dei uma olhadela rápido por essa lib (nunca a tinha visto :)) e o que vou dizer não sei se funciona porque não testei.

Visto que Html é um monoid podes usar as funções disso. Acho que podes fazer as seguintes transformações

fun1 = coisaA +++ coisaB +++ coisaC +++ coisaD
-- fica
fun1 = mconcat [coisaA, coisaB, coisaC, coisaD]


fun2 l = foldr (+++) (toHtml "") (map f l) where f = ...
-- fica
fun2 l = foldr mappend mempty (map f l)
-- fica
fun2 l = mconcat (map f l)
-- fica
fun2 = mconcat . map f

Deves ficar com o código mais diminuído :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

... mas quem quer eficiência, não me parece que escolha Haskell ;)

Haskell compilado é bastante rápido, comparável a C até.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Haskell compilado é bastante rápido, comparável a C até.

Apesar dos progressos que o Haskell tem feito, não me parece uma linguagem adequado quando o desempenho é essencial.

Ficam aqui alguns valores para comparar:

http://shootout.alioth.debian.org/u32q/benchmark.php?test=all&lang=all

http://shootout.alioth.debian.org/u32/benchmark.php?test=all&lang=all

Neste conjunto de casos de estudo, há um onde o Haskell se destaca, e que lhe permite ficar bem posicionado. Mesmo assim, ainda está visivelmente distante do C (e ainda mais do C++).

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