




























































































Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Programação Funcional em Haskell
Tipologia: Notas de estudo
1 / 163
Esta página não é visível na pré-visualização
Não perca as partes importantes!





























































































Francisco Vieira de Souza
Teresina-Pi Agosto de 2005
Esta Apostila representa a compila¸c˜ao de v´arios t´opicos, desenvolvidos por pesquisadores de renome, no campo da programa¸c˜ao funcional. Ela tem como objetivo servir de guia aos profis- sionais de Inform´atica que desejam ter um conhecimento inicial sobre o paradigma funcional de forma geral e, em particular, sobre programa¸c˜ao usando Haskell. Ultimamente, Haskell tem se tornado a linguagem funcional padr˜ao do discurso, j´a existindo v´arios interpretadores e compi- ladores para ela, al´em de v´arias ferramentas de an´alise de programas nela codificados (profiles).
Para atingir este objetivo, acreditamos que o estudo deva ser acompanhado de algum co- nhecimento, mesmo que m´ınimo, sobre a fundamenta¸c˜ao destas linguagens e da forma como elas s˜ao implementadas. Este conhecimento proporciona ao leitor uma vis˜ao das principais ca- racter´ısticas e propriedades destas linguagens. Em particular, ´e importante entender porque as t´ecnicas utilizadas na compila¸c˜ao das linguagens imperativas n˜ao se mostraram adequadas na compila¸c˜ao de linguagens funcionais.
Em 1978, John Backus advogou o paradigma funcional como o que oferecia a melhor solu¸c˜ao para a chamada “crise do software”. As linguagens funcionais s˜ao apenas uma sintaxe mais cˆomoda para o λ-c´alculo. David Turner [36] mostrou, em 1979, que a l´ogica combinatorial poderia ser extendida de forma a possibilitar a implementa¸c˜ao eficiente de linguagens funcionais. Esse trabalho provocou uma corrida em dire¸c˜ao `a pesquisa nesta ´area, gerando uma variedade de t´ecnicas de implementa¸c˜ao destas linguagens.
Dentre estas t´ecnicas, uma que tem sido adotada, com resultados promissores, ´e a utiliza¸c˜ao do λ-c´alculo como linguagem intermedi´aria entre a linguagem de alto n´ıvel e a linguagem de m´aquina. Os programas codificados em alguma linguagem funcional de alto n´ıvel s˜ao traduzidos para programas em λ-c´alculo e destes para programas em linguagem de m´aquina. Neste caso, o λ-c´alculo desempenha um papel semelhante ao que a linguagem Assembly exerce, como linguagem de montagem, na compila¸c˜ao de linguagens imperativas. Esta metodologia tem dado certo, uma vez que j´a se conhecem t´ecnicas eficientes de tradu¸c˜ao de programas em λ-c´alculo para programas execut´aveis, faltando apenas uma tradu¸c˜ao eficiente de programas codificados em uma linguagem funcional de alto n´ıvel para programas em λ-c´alculo.
Esta Apostila tem in´ıcio em seu primeiro Cap´ıtulo tratando das caracter´ısticas das lingua- gens funcionais, destacando suas vantagens em rela¸c˜ao as linguagens de outros paradigmas que utilizam atribui¸c˜oes destrutivas. Em seguida, ´e feita uma introdu¸c˜ao ao λ-c´alculo. Apesar do car´ater introdut´orio, achamos ser suficiente para quem quer dar os primeiros passos em dire¸c˜aoa aprendizagem desta t´ecnica. Os Cap´ıtulos subseq¨uentes se referem todos `a Programa¸c˜ao Fun- cional usando Haskell.
Por ser uma primeira tentativa, a Apostila cont´em erros e sua apresenta¸c˜ao did´atico-peda- g´ogica deve ser revista. Neste sentido, agradecemos cr´ıticas construtivas que ser˜ao objeto de an´alise e reflex˜ao e, por isto mesmo, muito bem-vindas.
Teresina-Pi, agosto de 2005.
Francisco Vieira de Souza
iv
e sim com as bibliotecas associadas, usadas na constru¸c˜ao de gr´aficos, banco de dados, interfaceamento, telefonia e servidores. Apesar de ainda n˜ao existirem muitas bibliotecas gr´aficas para as linguagens funcionais, muito esfor¸co tem sido feito nesta dire¸c˜ao, nos ultimos tempos.´ Haskell tem Fudgets, Gadgets, Haggis e Hugs Tk. SML/NJ tem duas: eXene e SML Tk. Haskell e ML tˆem ambas um poderoso sistema de m´odulos que tornam suas bibliotecas f´aceis de serem constru´ıdas.
2
Resumidamente, existem muitos fatores que desencorajam a escolha de linguagens funcio- nais como forma de se codificar programas. Para ser fortemente utilizada, uma linguagem deve suportar trabalho interativo, possuir bibliotecas extensas, ser altamente port´avel, ter uma im- plementa¸c˜ao est´avel e f´acil de ser instalada, ter depuradores e profilers, ser acompanhada de cursos de treinamentos e j´a ter sido utilizada, com sucesso, em uma boa quantidade de projetos.
Para Wadler [37] todos estes requisitos j´a s˜ao perfeitamente atendidos por algumas linguagens funcionais, por exemplo Haskell. Para ele o que ainda existe ´e um preconceito injustific´avel por parte de alguns programadores de outros paradigmas de programa¸c˜ao. No entanto, para a felicidade e consolo dos admiradores das linguagens funcionais, esta cultura tem se modificado, e de forma r´apida, ao longo dos ´ultimos anos.
A nosso ver, o que existe mesmo ´e a falta de informa¸c˜ao e conhecimento do que realmente ´e programa¸c˜ao funcional e quais as suas vantagens e desvantagens em rela¸c˜ao `a programa¸c˜ao em outros paradigmas. Esta Apostila tenta prover subs´ıdios para que seus usu´arios possam iniciar um processo de discuss˜ao sobre o tema. Para desencadear este processo, ´e necess´ario come¸car pelo entendimento da rela¸c˜ao entre a programa¸c˜ao funcional e a programa¸c˜ao estruturada.
Hoare enumerou seis princ´ıpios fundamentais da estrutura¸c˜ao de programas [24]:
3
Estas respostas tamb´em n˜ao s˜ao conclusivas, da mesma forma que as respostas dadas `a quest˜ao sobre programa¸c˜ao estruturada. E qual seria uma resposta afirmativa e definitiva? Usando a resposta anterior como base, pode-se dizer que ”as linguagens funcionais s˜ao altamente modulariz´aveis.”.
Esta ´e uma resposta afirmativa e que necessita apenas de mais um complemento para que a quest˜ao fique respondida em seu todo. Este complemento se refere `as caracter´ısticas que as linguagens funcionais apresentam e que proporcionam esta melhoria na modularidade dos sistemas. Estas caracter´ısticas podem ser sumarizadas na seguinte observa¸c˜ao: “a programa¸c˜ao funcional melhora a modularidade, provendo m´odulos menores, mais simples e mais gerais, atrav´es das fun¸c˜oes de alta ordem e lazy evaluation.
Estas duas caracter´ısticas, verificadas apenas nas linguagens funcionais, ´e que s˜ao res- pons´aveis pela grande modularidade por elas proporcionada. Dessa forma, as linguagens funci- onais s˜ao altamente estruturadas e se candidatam, com grande chance de ˆexito, como solu¸c˜oes para a t˜ao propalada “crise do software” dos anos 80.
Para continuar esta viagem pelo mundo da programa¸c˜ao funcional, tentando entender sua fundamenta¸c˜ao te´orica ´e necess´ario conhecer tamb´em como as linguagens s˜ao implementadas. Inicialmente vamos nos referir `a implementa¸c˜ao de linguagens tradicionais e depois particulari- zaremos para o caso das funcionais.
Programar ´e modelar problemas do mundo real ou imagin´ario em um computador, usando algum paradigma de programa¸c˜ao. Desta forma, os problemas s˜ao modelados em um n´ıvel de abstra¸c˜ao bem mais alto atrav´es de especifica¸c˜oes formais, feitas utilizando uma linguagem de especifica¸c˜ao formal. Existem v´arias linguagens de especifica¸c˜ao formal: Lotos, Z, VDM, Redes de Petri, entre outras. A escolha de uma delas est´a diretamente ligada ao tipo da aplica¸c˜ao e `a experiˆencia do programador. Por exemplo, para especificar dispositivos de hardware ´e mais natural se usar Redes de Petri, onde pode-se verificar a necessidade de sincroniza¸c˜ao e podem ser feitas simula¸c˜oes para a an´alise de desempenho ou detectar a existˆencia, ou n˜ao, de inconsistˆencias.
Muitas ferramentas gr´aficas j´a existem e s˜ao utilizadas na an´alise de desempenho de dispo- sitivos especificados formalmente e podem ser feitos prot´otipos r´apidos para se verificar a ade- quabilidade das especifica¸c˜oes `as exigˆencias do usu´ario, podendo estes prot´otipos serem parte integrante do contrato de trabalho entre o programador e o contratante. Mais importante que isto, a especifica¸c˜ao formal representa um prova da corretude do programa e que ele faz exata- mente o que foi projetado para fazer. Isto pode ser comparado com a garantia que um usu´ario tem quando compra um eletrodom´estico em uma loja. Esta garantia n˜ao pode ser dada pelos testes, uma vez que eles s´o podem verificar a presen¸ca de erros, nunca a ausˆencia deles. Os testes representam uma ferramenta importante na ausˆencia de uma prova da corretude de um
5
programa, mas n˜ao representam uma prova. O uso de testes requer que eles sejam bem proje- tados e de forma objetiva, para que tenham a sua existˆencia justificada. Com a especifica¸c˜ao pronta, ela deve ser implementada em uma linguagem de programa¸c˜ao.
Figura 1: Relacionamento entre Computador e Linguagens.
A linguagem de programa¸c˜ao a ser escolhida depende da aplica¸c˜ao. Em muitos casos, este processo ´e t˜ao somente uma tradu¸c˜ao, dependendo da experiˆencia do programador com a lingua- gem de programa¸c˜ao escolhida. No caso das linguagens funcionais, este processo ´e muito natural, uma vez que as especifica¸c˜oes formais s˜ao apenas defini¸c˜oes impl´ıcitas de fun¸c˜oes, restanto ape- nas a tradu¸c˜ao destas defini¸c˜oes impl´ıcitas para defini¸c˜oes expl´ıcitas na linguagem funcional escolhida^3. Resta agora a tradu¸c˜ao destes programas em linguagens de alto n´ıvel para progra- mas execut´aveis em linguagem de m´aquina, sendo este o papel do compilador. Este processo est´a mostrado na Figura 1.
A compila¸c˜ao de programas codificados em linguagens imperativas, normalmente, ´e feita em duas etapas [1]. Na primeira delas, ´e feita uma tradu¸c˜ao do programa escrito em linguagem de alto n´ıvel para um programa codificado em linguagem intermedi´aria, chamada de linguagem de montagem (Assembly). Na etapa seguinte, ´e feita a tradu¸c˜ao do programa em linguagem de montagem para o programa execut´avel, em linguagem de m´aquina. Este processo est´a mostrado na Figura 2.
Figura 2: Processo de compila¸c˜ao das linguagens imperativas. (^3) Estas formas de defini¸c˜ao de fun¸c˜oes s˜ao mostradas no Cap´ıtulo 1 desta Apostila.
Uma t´ecnica usada com sucesso na implementa¸c˜ao de linguagens funcionais consiste na imple- menta¸c˜ao do λ-c´alculo usando a redu¸c˜ao das λ-express˜oes para λ-express˜oes mais simples, at´e atingir uma forma normal, se ela existir. O resultado desta t´ecnica foi um sistema que ficou conhecido na literatura como m´aquinas abstratas. A primeira m´aquina abstrata foi desenvolvida por Peter Landin em 1964 [20], que ganhou o alcunha de m´aquina SECD, devido ao seu nome (Stack, Environment, Code, Dump). A m´aquina SECD usa a pilha S para a avalia¸c˜ao das λ-express˜oes Codificadas, utilizando o ambiente E.
Uma otimiza¸c˜ao importante na m´aquina SECD foi transferir alguma parcela do tempo de execu¸c˜ao para o tempo de compila¸c˜ao. No caso, isto foi feito transformando as express˜oes com nota¸c˜ao infixa para a nota¸c˜ao polonesa reversa que ´e adequada para ser executada em pilha, melhorando o ambiente de execu¸c˜ao. Para diferenciar da m´aquina SECD, esta m´aquina foi chamada de SECD2.
Em 1979, David Turner [36] desenvolveu um processo de avalia¸c˜ao de express˜oes em SASL (uma linguagem funcional) usando o que ficou conhecida como a m´aquina de combinadores. Ele utilizou os combinadores S, K e I do λ-c´alculo^5 para representar express˜oes, em vez de λ-express˜oes, utilizando para isto um dos combinadores acima citados, sem vari´aveis ligadas [7]. Turner traduziu diretamente as express˜oes em SASL para combinadores, sem passar pelo est´agio intermedi´ario das λ-express˜oes. A m´aquina de redu¸c˜ao de Turner foi chamada de M´aquina de Redu¸c˜ao SK e utilizava a redu¸c˜ao em grafos como m´etodo para sua implementa¸c˜ao. Esta m´aquina teve um impacto muito intenso na implementa¸c˜ao de linguagens aplicativas, pelo ganho em eficiˆencia, uma vez que ela n˜ao utilizava o ambiente da m´aquina SECD, mas tirava partido do compartilhamento que conseguia nos grafos de redu¸c˜ao.
Um outro pesquisador que se tornou famoso no desenvolvimento de m´aquinas abstratas foi Johnsson, a partir de 1984, quando ele deu in´ıcio a uma s´erie de publica¸c˜oes [16, 17, 18] sobre este tema, culminando com sua Tese de Doutorado, em 1987 [19], onde ele descreve uma m´aquina abstrata baseada em supercombinadores que eram combinadores abstra´ıdos do programa de usu´ario para algumas necessidades particulares. A m´aquina inventada por Johnsson ficou co- nhecida pela M´aquina G e se caracterizou por promover uma melhoria na granularidade dos programas, que era muito fina na m´aquina de redu¸c˜ao de Turner. Uma otimiza¸c˜ao importante desta m´aquina foi a utiliza¸c˜ao de uma segunda pilha na avalia¸c˜ao de express˜oes aritm´eticas ou outras express˜oes estritas.
Figura 4: O processo de compila¸c˜ao das linguagens funcionais adotado em ΓCMC.
V´arias outras m´aquinas abstratas foram constru´ıdas com bons resultados. Entre elas podem ser citadas a m´aquina GMC e a m´aquina Γ, idealizadas por Rafael Lins, da Universidade Federal
(^5) Combinadores e supercombinadores s˜ao temas do λ-c´alculo, objeto de estudo do Cap´ıtulo 2, deste trabalho.
de Pernambuco [8].
Al´em destas, uma que tem se destacado com excelentes resultados ´e a m´aquina ΓCMC, tamb´em de Rafael [21, 8], onde um programa codificado em SASL ´e traduzido para um programa em Ansi C. Este processo est´a mostrado na Figura 4.
A escolha da linguagem C se deve ao fato de que os compiladores de C geram c´odigos reco- nhecidamente port´ateis e eficientes. A m´aquina ΓCMC ´e baseada nos combinadores categ´oricos que se fundamentam na Teoria das Categorias Cartesianas Fechadas, recentemente utilizada em diversas ´areas da Computa¸c˜ao, sendo hoje um tema padr˜ao do discurso, nos grandes encontros e eventos na ´area da Inform´atica [9].
Esta Apostila ´e composta desta Introdu¸c˜ao e 6 (seis) Cap´ıtulos. Nesta Introdu¸c˜ao, ´e colocada, de forma resumida, a importˆancia das linguagens funcionais e a necessidade de estudar o λ- c´alculo e justificar sua escolha como a linguagem intermedi´aria entre as linguagens funcionais e as linguagens de m´aquina. E necess´´ ario saber que as linguagens funcionais s˜ao importantes porque aumentam a modularidade dos sistemas atrav´es das fun¸c˜oes de alto n´ıvel e do mecanismo de avalia¸c˜ao pregui¸cosa.
O Cap´ıtulo 1 ´e dedicado `a fundamenta¸c˜ao das linguagens funcionais, abordando as princi- pais diferen¸cas entre elas e as linguagens de outros paradigmas. O mundo das linguagens de programa¸c˜ao ´e dividido entre o mundo das express˜oes e o mundo das atribui¸c˜oes, evidenciando as vantagens do primeiro mundo em rela¸c˜ao ao segundo.
No Cap´ıtulo 2, ´e introduzido o λ-c´alculo, sua evolu¸c˜ao hist´orica e como ele ´e usado nos dias atuais. A teoria ´e colocada de maneira simples e introdut´oria, dado o objetivo da Apostila.
No Cap´ıtulo 3, inicia-se a programa¸c˜ao em Haskell. S˜ao mostrados seus construtores e uma s´erie de exemplos, analisando como as fun¸c˜oes podem ser constru´ıdas em Haskell. S˜ao mostrados os tipos de dados primitivos adotados em Haskell e os tipos estruturados mais simples que s˜ao as tuplas. No Cap´ıtulo, tamb´em s˜ao mostrados os esquemas de provas de programas, juntamente com v´arios exerc´ıcios, resolvidos ou propostos.
O Cap´ıtulo 4 ´e dedicado a listas em Haskell. Este Cap´ıtulo se torna necess´ario, dada a importˆancia que este tipo de dado tem nas linguagens funcionais. Neste Cap´ıtulo, s˜ao mostradas as compreens˜oes ou express˜oes ZF e tamb´em ´e mostrada a composi¸c˜ao de fun¸c˜oes como uma caracter´ıstica apenas das linguagens funcionais, usada na constru¸c˜ao de fun¸c˜oes. Um tema importante e que ´e discutido neste Cap´ıtulo se refereas formas de provas da corretude de programas em Haskell, usando indu¸c˜ao estrutural sobre listas. No Cap´ıtulo s˜ao mostrados v´arios exemplos resolvidos e, ao final, s˜ao colocados v´arios exerc´ıcios `a aprecia¸c˜ao do leitor.
No Cap´ıtulo 5, s˜ao mostradas as type class, como formas de incluir um determinado tipo de dados em em uma classe de tipos que tenham fun¸c˜oes em comum, dando origem `a sobrecarga como forma de polimorfismo. Tamb´em s˜ao mostrados os tipos de dados alg´ebricos, o sistema de m´odulos adotado em Haskell, os tipos de dados abstratos e o tratamento de exce¸c˜oes. O Cap´ıtulo termina com uma revis˜ao sobre o sistema de avalia¸c˜ao lazy, notadamente na constru¸c˜ao de listas potencialmente infinitas.
O Cap´ıtulo 6 ´e dedicado `as opera¸c˜oes de entrada e sa´ıda em Haskell, evidenciado o uso de arquivos ou dispositivos como sa´ıda ou como entrada. Este processo em Haskell ´e feito atrav´es do mecanismo de “a¸c˜oes”, cuja semˆantica representa o conte´udo principal do Cap´ıtulo.
A Apostila termina com as principais referˆencias bibliogr´aficas consultadas durante s sua elabora¸c˜ao.
”We can now see that in a lazy implementation based on suspensions, we can treat every function in the same way. Indeed, all functions are treated as potentially non-strict and their argument is automatically suspended. Later, is and when it is needed, it will be unsuspended (strictly evaluated).” (Antony D. T. Davie in [7])
A programa¸c˜ao funcional teve in´ıcio antes da inven¸c˜ao dos computadores eletrˆonicos. No in´ıcio do s´eculo XX, muitos matem´aticos estavam preocupados com a fundamenta¸c˜ao matem´atica, em particular, queriam saber mais sobre os conjuntos infinitos. Muito desta preocupa¸c˜ao aconteceu por causa do surgimento, no final do s´eculo XIX, de uma teoria que afirmava a existˆencia de v´arias ordens de infinitos, desenvolvida por George Cantor (1845-1918) [24]. Muitos matem´aticos, como Leopold Kronecker (1823-1891), questionaram a existˆencia destes objetos e condenaram a teoria de Cantor como pura “enrola¸c˜ao”. Estes matem´aticos defendiam que um objeto matem´atico s´o poderia existir se, pelo menos em princ´ıpio, pudesse ser constru´ıdo. Por este motivo, eles ficaram conhecidos como “construtivistas”.
Mas o que significa dizer que um n´umero, ou outro objeto matem´atico, seja construt´ıvel? Esta id´eia foi desenvolvida lentamente, ao longo de muitos anos. Guiseppe Peano (1858-1932), um matem´atico, l´ogico e linguista, escreveu “Formulaire de Math´ematique” (1894-1908), onde mostrou como os n´umeros naturais poderiam ser constru´ıdos atrav´es de finitas aplica¸c˜oes da fun¸c˜ao sucessor. Come¸cando em 1923, Thoralf Skolen (1887-1963) mostrou que quase tudo da teoria dos n´umeros naturais poderia ser desenvolvido construtivamente pelo uso intensivo de defini¸c˜oes recursivas, como as de Peano. Para evitar apelos question´aveis sobre o infinito, pareceu razo´avel chamar um objeto de construt´ıvel se ele pudesse ser constru´ıdo em um n´umero finito de passos, cada um deles requerendo apenas uma quantidade finita de esfor¸co. Assim, nas primeiras d´ecadas do s´eculo XX, j´a existia consider´avel experiˆencia sobre as defini¸c˜oes recursivas de fun¸c˜oes sobre os n´umeros naturais.
A cardinalidade (quantidade de elementos) dos conjuntos finitos era f´acil de ser conhecida, uma vez que era necess´ario apenas contar seus elementos. J´a para os conjuntos infinitos, esta t´ecnica n˜ao podia ser aplicada. Inicialmente, era necess´ario definir o que era realmente um conjunto infinito. Foi definido que um conjunto era infinito se fosse poss´ıvel construir uma correspondˆencia biun´ıvoca entre ele e um subconjunto pr´oprio dele mesmo. Foram definidos os conjuntos infinitos enumer´aveis, que foram caracterizados pelos conjuntos infinitos para os quais
11
fosse poss´ıvel construir uma correspondˆencia biun´ıvoca com o conjunto dos n´umeros naturais, N. Assim, todos os conjuntos infinitos enumer´aveis tinham a mesma cardinalidade, que foi definida por ℵ 01. Assim, a cardinalidade do conjunto dos n´umeros inteiros, Z, tamb´em ´e ℵ 0 , uma vez que ´e poss´ıvel construir uma correspondˆencia biun´ıvoca entre Z e N. Os conjuntos infinitos com os quais n˜ao fosse poss´ıvel estabelecer uma correspondˆencia biun´ıvoca entre eles e N, foram chamados de infinitos n˜ao enumer´aveis. A cardinalidade do conjuntos dos n´umeros reais, R, que ´e infinito n˜ao enumer´avel, ´e 2ℵ^0.
Na d´ecada de 1930, existiram muitas tentativas de formaliza¸c˜ao do construtivismo, procurando caracterizar o que era camputabilidade efetiva, ou seja, procurava-se saber o que realmente podia ser computado. Uma das mais famosas tentativas foi a defini¸c˜ao de Turing sobre uma classe de m´aquinas abstratas, que ficaram conhecidas como “m´aquinas de Turing”, que realizavam opera¸c˜oes de leitura e escritas sobre uma fita de tamanho finito. Outra t´ecnica, baseada mais diretamente nos trabalhos de Skolen e Peano, consistia no uso de “ fun¸c˜oes recursivas gerais”, devida a G¨odel. Uma outra t´ecnica, com implica¸c˜ao importante na programa¸c˜ao funcional, foi a cria¸c˜ao do λ-c´alculo, desenvolvido por Church e Kleene, no in´ıcio da d´ecada de 1930. Outra no¸c˜ao de computabilidade, conhecida como “Algoritmos de Markov”, tamb´em foi desenvolvida nesta mesma ´epoca. O que ´e importante ´e que todas estas no¸c˜oes de computabilidade foram provadas serem equivalentes. Esta equivalˆencia levou Church, em 1936, a propor o que ficou conhecida como a Tese de Church^2 , onde ele afirmava que “uma fun¸c˜ao era comput´avel se ela fosse primitiva recursiva” [5].
Isto significa que, j´a na d´ecada anterior `a d´ecada da inven¸c˜ao do computador eletrˆonico, muitos matem´aticos e l´ogicos j´a haviam investigado, com profundidade, a computabilidade de fun¸c˜oes e identificado a classe das fun¸c˜oes comput´aveis como a classe das fun¸c˜oes primitivas recursivas.
O pr´oximo invento importante na hist´oria da programa¸c˜ao funcional foi a publica¸c˜ao de John McCarthy, em 1960, sobre LISP. Em 1958, ele investigava o uso de opera¸c˜oes sobre listas ligadas para implementar um programa de diferencia¸c˜ao simb´olica. Como a diferencia¸c˜ao ´e um processo recursivo, McCarthy sentiu-se atra´ıdo a usar fun¸c˜oes recursivas e, al´em disso, ele tamb´em achou conveniente passar fun¸c˜oes como argumentos para outras fun¸c˜oes. McCarthy verificou que o λ-c´alculo provia uma nota¸c˜ao muito conveniente para estes prop´ositos e, por isto mesmo, ele resolveu usar a nota¸c˜ao de Church em sua programa¸c˜ao.
Em 1958, foi iniciado um projeto no MIT com o objetivo de construir uma linguagem de programa¸c˜ao que incorporasse estas id´eias. O resultado ficou conhecido como LISP 1, que foi descrita por McCarthy, em 1960, em seu artigo “Recursive Functions of Symbolic Expressions and Their Computation by Machine” [24]. Este artigo mostrou como v´arios programas com- plexos podiam ser expressos por fun¸c˜oes puras operando sobre estruturas de listas. Este fato ´e caracterizado, por alguns pesquisadores, como o marco inicial da programa¸c˜ao funcional.
No final da d´ecada de 1960 e in´ıcio da d´ecada de 1970, um grande n´umero de cientistas da Computa¸c˜ao come¸caram a investigar a programa¸c˜ao com fun¸c˜oes puras, chamada de “pro- grama¸c˜ao aplicativa”, uma vez que a opera¸c˜ao central consistia na aplica¸c˜ao de uma fun¸c˜ao a seu argumento. Em particular, Peter Landin (1964, 1965 e 1966) desenvolveu muitas das id´eias centrais para o uso, nota¸c˜ao e implementa¸c˜ao das linguagens de programa¸c˜ao aplicativas, sendo importante destacar sua tentativa de traduzir a defini¸c˜ao de uma linguagem n˜ao funcional, Algol
(^1) ℵ ´e uma letra do alfabeto ´arabe, conhecida por Aleph. (^2) Na realidade, n˜ao se trata de uma tese, uma vez que ela nunca foi provada. No entanto, nunca foi exibido um contra-exemplo, mostrando que esta conjectura esteja errada.
12