Conteúdos da cadeira

Lambda, currying e ordem superior

Aplicação parcial, secções de operadores e pipelines com map, filter e foldr.

Markdown

Perguntar sobre esta página

ChatGPTClaudePerplexityGeminiCopiar e abrir

Envia o link e pede à IA para ler a página. No Gemini, cola a pergunta copiada.

Ver pergunta para copiar
Nesta página

Toda a função em Haskell recebe na verdade um só argumento. Uma função “de dois argumentos” é uma função que recebe o primeiro e devolve outra função à espera do segundo. Esta convenção chama-se currying e transforma a aplicação parcial, passar só alguns argumentos, na ferramenta mais usada da linguagem.

Aplicação parcial

soma :: Int -> Int -> Int
soma x y = x + y

soma5 :: Int -> Int
soma5 = soma 5

soma 5 é uma função à espera do segundo argumento, por isso soma5 38. O mesmo vale para operadores por meio de secções: (>= 9.5) é a função que testa se o seu argumento é maior ou igual a 9.5, e (* 2) é a função que dobra. Quando precisares de uma função pequena só uma vez, escreve-a anónima com lambda: (\x -> x * 2) lê-se “a função que a x associa x * 2”.

Isto generaliza o que viste em FP: o lambda do Python e o \ do Haskell são o mesmo gesto, mas em Haskell a aplicação parcial dispensa a maioria dos lambdas.

map, filter e foldr

O prelúdio traz as três de ordem superior que já conheces, com tipos honestos:

map    :: (a -> b) -> [a] -> [b]
filter :: (a -> Bool) -> [a] -> [a]
foldr  :: (a -> b -> b) -> b -> [a] -> b

map transforma, filter seleciona, foldr combina tudo num valor partindo da direita com um acumulador inicial. sum é foldr (+) 0 e length é foldr (\_ n -> n + 1) 0. Quando o problema for “transformar cada um”, “ficar só com alguns” ou “resumir tudo”, começa por estas antes de escreveres recursão à mão.

Exemplo completo: média das aprovações

Dada uma pauta, calcular a média só das notas de aprovação (maior ou igual a 9.5):

mediaAprovados :: [Int] -> Double
mediaAprovados notas = fromIntegral soma / fromIntegral n
  where
    ap   = filter (>= 9.5) notas
    soma = sum ap
    n    = length ap

Segue com [8,12,6,15,10]. O filter (>= 9.5) usa uma secção para ficar com [12,15,10]. Depois soma vale 37 e n vale 3. A divisão / exige Double dos dois lados, mas soma e n são Int: fromIntegral converte cada um, como prometido na página de classes. O resultado é 12.333333333333334.

O bloco where define nomes locais partilhados, avaliados só se usados. É o sítio para os passos intermédios com nome, enquanto o corpo da função fica a frase principal.

Ver o ficheiro no GitHub

À tua maneira

Escolhe como preferes ler.

Aparência
Ajustar cores e largura
Cor de destaque do tema FEUP
Tipo de letra

Álgebra, lógica e uma ideia de cada vez.

As tuas escolhas ficam guardadas neste navegador.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.