Jump to content

concatena3 = foldl (\a b@(y:ys)->a++b) [] -- por que aceita e dá erro no final


crislanio_macedo
 Share

Recommended Posts

Olá pessoal, aconteceu um caso que chega até engraçado, vejamos as funções abaixo.

concatena3 = foldl (\a b@(y:ys)->a++b) [] -- por que aceita e dá erro no final
concatena2 = foldl (\x xs->x++xs ) []
concatena4 = foldl1 (\a@(x:xs) b@(y:ys)->a++b) -- aceita e não erro no final

Agora queria que os srs, me dessem uma explicação do por que o erro na função concatena3 ao querer usar \a@(x:xs)

*Main> concatena2 [[1,2] ,[2,3]]
[1,2,2,3]
*Main> concatena4 [[1,2] ,[2,3]]
[1,2,2,3]
*Main> concatena3 [[1,2] ,[2,3]]
[1,2,2,3]
---------------------------------
*Main> concatena3 [[1,2] ,[2,3]]
*** Exception: Exercicios-2Entrega.hs:256:21-44: Non-exhaustive patterns in lambda

concatena3 = foldl (\a@(x:xs) b@(y:ys)->a++b) [] -- por que aceita e dá erro no final

O erro como podem ver na concatena3 acontece, mas não tenho explicação do porque isso acontece.

Edited by crislanio_macedo
Link to comment
Share on other sites

crislanio_macedo,

Pelo que percebi, a tua função concatena3 deixa de funcionar quando substituis o argumento a por a@(x:xs) (o teu post estava um pouco confuso -- deverias ter colocado a redefinição da função entre os dois exemplos e não no final dos mesmos).

Passando ao problema propriamente dito, a questão é relativamente simples e deve-se a um erro que já cometeste noutro tópico e para o qual já foste avisado (irás perceber de seguida).

Antes de começarmos, podemos pegar na tua função anónima e torná-la numa função «normal» para perceberes melhor:

-- Este código é em tudo equivalente ao teu, apenas mais compreensível
concatena3 = foldl f []   -- este [] é o elemento inicial
 where
   f a@(x:xs) b@(y:ys) = a ++ b

Quando a função foldl invoca a tua função anónima pela primeira vez, passa-lhe como argumentos o elemento inicial (que no teu caso é []) e o primeiro elemento da lista a processar (que é [1,2]).

O problema surge na definição dos argumentos formais da função: tu disseste ao compilador que o primeiro argumento (de nome a) é uma lista com pelo menos um elemento ((x:xs)) e nesta primeira invocação esse argumento é nada mais nada menos do que uma lista vazia, [].

O compilador queixa-se porque [] é incompatível com (x:xs), mas o erro que emite diz algo diferente: diz que não definiste padrões exaustivos -- é uma forma de dizer que não previste todos os casos possíveis, aqui especificamente o caso do primeiro argumento ser uma lista vazia. Se tivesses deixado apenas o a a identificar o primeiro argumento, tudo estaria bem porque seria compatível com todos os tipos de listas (vazias ou não).

E agora voltamos ao que eu referi no início: já te avisámos noutro tópico para a inclusão de código desnecessário, e embora das outras vezes fosse completamente redundante, neste caso acabou mesmo por te criar um erro em tempo de execução, o que é grave.

Regra geral, quanto mais simples, melhor.

E já agora, podemos simplificar a tua função muito mais:

concatena3 = foldl (\a@(x:xs) b@(y:ys) -> a ++ b) [] =
            -- os (x:xs) e (y:ys) eram inúteis (e até errados, como vimos)   
          = foldl (\a b -> a ++ b) [] =
            -- se f a b = a ++ b, então f = (++)
          = foldl (++) []
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.