Nome TextoResumo
0 ALLEF KRISTIAN TAVARES ROCHA # Resumo Semana 2 ## Calculo lambda -- Sintaxe: λx . e \x-> e (em haskell) onde x: variável e: escopo de x -- Redução β (\x -> e1) e2 => e1[x := e2] -- Combinador Ω: (\x -> x x) (\x -> x x) =β> (\x -> x x) (\x -> x x) -- Funcionalidades: * Booleanos: Verdadeiro = \x y -> x Falso = \x y -> y IF = \b x y -> b x y * Registros: PAIR = \x y -> (\b -> IF b x y) FST = \p -> p Verdadeiro SND = \p -> p Falso * Numeros: ZERO = \f x -> x UM = \f x -> f x DOIS = \f x -> f (f x) ... * Recursão: Utilizando o operador Y: Y = \f -> (\x -> f (x x)) (\x -> f (x x)) ## Conceitos Básicos * Códigos concisos / declarativos * Imutabilidade * Recursão (não há laços) * Funções de alta ordem: funçoes como parâmetros * Tipos polimórficos * Avaliação preguiçosa -- Lista: sequência de elementos do mesmo tipo -- Tuplas: sequência finita de componentes, com tipos não necessariamente iguais -- Funções: foo :: T1 -> T2 (mapa do tipo T1 para o tipo T2) -- Condicionais: foo n = if n == 0 then x1 else x2 foo n = | n == 0 = x1 | n < 0 = x2 | otherwise = x3 -- Funcionalidades das listas * Concatenação: (:) 1 : 2 : 3 : [] = [1,2,3] * Faixas: (..) [0,2..6] = [0,2,4,6] * Lista infinita: [0,2..] = [0,2,4,...] * Recuperar elemento: lista!!n n-esimo head lista primeiro tail lista exceto primeiro last lista ultimo take n lista n primeiros drop n lista n ulimos sum lista product lista null lista lista vazia? length * Compressão de listas Ex: todos os naturais primos [x | x <- [1..] , primo x] * zip: zip [1,2,3] ['a','b','c','d'] = [(1,'a'),(2,'b'),(3,'c')] * pairs: pairs [1,2,3] = [(1,2),(2,3)] * and/or: and [True, False, True] = False or [True, False, True] = True
1 ANABEL CRISTINA MOREIRA DE FREITAS Computabilidade -> possibilidade de resolver um problema seguindo um algoritmo Alonzo Church -> Calculo λ Tudo o que é calculavel no calculo λ é computavel na máquina de turing problemas: decisão, função, busca, otimização Calculo λ precisa apenas de funções sintaxe composto de variaveis, definição e aplicação de funções função identidade: λx.x λ - \ . - -> programa é definido por uma expressão 'e' ou termos λ variável abstração \x -> e (p/ qualquer x compute e) aplicação e1 e2 aplique o argumento e2 na função e1(e1(e2)) funções que recebem dois argumentos sao encadeadas alfa e beta
2 ANANDA DE OLIVEIRA GONÇALVES ANTENOR
4 ANDRE BELTRAME KRUSS Haskell surgiu em 1990, com o propósito de ser uma linguagem puramente funcional. Apesar disso, com o tempo Haskell passou a ser aplicado não só no âmbito da pesquisa, mas também na prática. Por ser uma linguagem funcional, os códigos em Haskell geralmente são menores (o que deve ser feito é explicitado pelo programador). Além disso, Haskell é imutável, ou seja não existe de fato variáveis (são apenas nomes) e por isso, não há os tradicionais laços de repetição igual outras linguagens; as repetições são implementadas através de funções recursivas. Haskell também permite a implementação de funções que aceitam parâmetros de qualquer tipo (polimorfismo). Os blocos de código em Haskell são definidos por indentação. Possui diversos tipos básicos de dados, como boleanos, caracteres (do sistema Unicode), strings, inteiros, float e double. Também há suporte para listas e tuplas, as listas não possuem tamanho definido, enquanto que tuplas são sequências finitas de elementos. Funções em Haskell podem possuir diversos argumentos e mapeiam para um determinado tipo de retorno. Haskell suporta estruturas condicionais if e else, assim como Guards que são expressões que ajudam a simplificar o excesso de uso de if-else encadeados.
5 ANDRE RICCA YOSHIDA Cálculo Lambda: - Descreve a computação apenas utilizando funções. É composto por variáveis, definição de funções e aplicação das mesmas. Condicional utilizando Lambda: - IF = \b x y -> b x y Números de Church: - Forma alterantiva de definir os números naturais. Podemos representar um número natural N através de uma função, que toma uma função F como parametro e retorna N vezes F. Combinador Y: - Em cálculo lambda, não é possível utilizar uma recursão pura. Para isso aplicamos o combinador Y, que nos permite escrever uma expressão lambda que se repete indefinidas vezes. O problema é que haskell não aceita tipos infinitos. Para contornar o problema, precisamos definir um operador de ponto fixo. Conceitos básicos de haskell: - Funções podem receber funções como parametro. - Nos permite definir tipos polimórficos. Exemplo: length :: [a] -> Int, onde "a" significa que a função pode receber qualquer tipo. - Blocos lógicos definidos por identação. - Cláusula WHERE, define nomes intermediários para variáveis.
6 ANDRESSA TEIXEIRA MENEZES Na aula da semana 2 aprendemos a verificar os tipos das funções interpreta-los corretamente, avaliando desde os tipos de entrada e suas restrições até a aplicação de "melhorias" na implementação do código, como o uso de Guards para melhor avaliar as condições do problema. Além disso, também foram introduzidos os conceitos de listas e algumas funções com as quais podemos manipula-las e/ou conhecer informações acerca daquela lista como por exemplo a função head, que retorna o primeiro item da lista xs, ou a função tail, que retorna uma lista xs' que contém todos os elementos de uma lista xs mas sem o primeiro elemento. Também foi apresentado o uso das tuplas dentro das listas e como operar com elas.
3 ANDRÉ ANDERSON DE JESUS OLIVEIRA
7 ANGELO MAEDA ROJAS Essa semana foi dividida em dois tópicos diferentes: o cálculo lambda e o básico de Haskell. O lambda foi criado pelo Alonzo Church na década de 1930 e é o elemento mais básico da computação, ele é composto por três elementos: variáveis, definições de variáveis e aplicação de funções. O restante dessa parte são formas de como representar as operações mais comuns da computação utilizando-se somente lambda, como booleanos, registros, números e recursão. Um exemplo de uma expressão lambda é (\x y -> x y) k, no qual “k” é uma variável livre, utilizando-se beta-redução chega-se em: \x -> x k, o termo final é considerado “normal”, pois não pode sofrer mais reduções beta! Essa parte da matéria possui muitos detalhes, é bom dar uma revisada em algum momento oportuno! O segundo tópico da semana foi o básico da programação em Haskell, acredito que tenha captado bem a matéria, apesar de achar alguns detalhes de Haskell bem estranhos. Com exceção do último exercício, foi bem fluído a resolução dessa primeira lista.
8 ANTONIO DUARTE CANTANHEDE NETO Haskell é uma linguagem funcional cujo funcionamento se baseia no cálculo λ. O cálculo λ é uma alternativa teórica às máquinas de Turing como fundamento teórico para os computadores modernos. Com funções λ é possível construir todos os tipos básicos, estruturas de dados e operadores que as linguagens de programação não funcionais costumam ter. O compilador GHC suporta nativamente vários tipos básicos de dados. Alguns deles são: Bool (booleanos); Char (caracteres); String (cadeias de caracteres); Int (inteiros de -2^63 até 2^63 -1 ); Integer (inteiros de precisão arbitrária);Float (valores em ponto-flutuante com precisão simples; Double (valores em ponto-flutuante com precisão dupla). Haskell também tem suporte a listas. data [] a = [] | a : [a] onde “:” é o operador cons, de concatenação. Uma lista ou é a lista vazia, ou é uma concatenação de um elemento do tipo a com uma lista do tipo ª Listas podem ser “infinitas” - não infinitas de fato, mas seus elementos são avaliados apenas quando necessário (lazy evaluation). Algumas das funções básicas para manipulação de listas são: !! → recupera o i-ésimo elemento da lista head → retorna o primeiro elemento da lista tail → retorna a lista sem o primeiro elemento take → retorna os n primeiros elementos da lista drop → retorna a lista sem os n primeiros elementos sum e product → retornam a somatória e produtória de uma lista É possível concatenar listas, realizar “pattern matching” com as mesmas e mesclar listas.
11 BRUNA ISHIDA O Cálculo lambda é uma maneira de representar por nomes e substituições as regras e funções de algum contexto. A linguagem possui 3 grandes elementos: variáveis, definições de funções e aplicação de funções O lambda é utilizado para representar as funções. O Haskell surgiu como uma linguagem 100% funcional. Ele tem como características: Códigos concisos e declarativos (fortemente tipada), possui recursividade, funções que podem receber parâmetros, possui tipos polimórficos e uma avaliação preguiçosa(o código é rodado apenas quando requisitado) Essa linguagem utiliza de tipos básicos como por exemplo: Int, Integer(não tem limite de valores como o Int), String, Float, Double, Char, e Bool. Além disso, há a existência de listas e tuplas. Para a tipagem da função, é utilizado dos tipos básico. Assim, pode-se montar as diversas transformações que ocorrem no decorrer de uma função. Exite uma definição chamada Overloaded types, ou seja, existem funções e comandos que podem ser utilizados por diversos tipos básicos e que trazem resultados diferentes para cada tipo,como por exemplo a soma (+), porém . Para abranger todos esses tipos, é possível passar um valor genérico que especifique o grupo. EX: Num a => a -> a. Em Haskell, não já a possibilidade de realizar um for ou um while, uma vez que as variáveis não podem alterar de valor. Assim, se for necessária a iteração sobre um array, é necessário utilizar do mapping, que realizará a passagem pelos elementos desse array.
12 BRUNA MIRELLI XAVIER GONCALVES Resumo - Bruna Mirelli - 11008116 Semana 2 1.Cálculo Lambda Os estudos de Church e Turing sobre a computabilidade e sobre problemas calculáveis produziram uma massa conceitual que baseou a formação do cálculo lambda como linguagem que possui sintaxe e semântica. Esta linguagem pretende descrever a computação com apenas o uso de funções. Sua sintaxe utiliza i) variáveis que assumem valores, ii) abstrações de funções lambda que recebem um parâmetro e possuem um retorno que depende do que é definido no corpo da função, e iii) aplicações que são as chamadas de função. E sua semântica é baseada na reescrita de expressões por um passo alfa que renomeia parâmetros formais, ou por um passo beta que utiliza uma variável livre para fazer a aplicação de uma expressão. Essa linguagem também permite haver aspectos que possibilitam muitas utilizações como: booleanos, registros, números, funções e recursão. 2. Conceitos Básicos de Haskell - Parte 1 A linguagem Haskell utiliza o paradigma funcional e foi desenvolvida com base nos conceitos consolidados pelo Cálculo Lambda. Permite a escrita de códigos declarativos, menos específicos sobre o modo de resolução e também mais compactos. Não utiliza conceito de variável e evita elementos com valores mutáveis, que são contornados pelo uso da recursividade. Pode passar funções como parâmetro para outras. Possui tipos polimórficos de dados. Apenas computa o resultado de uma expressão quando necessário. Contém tipos básicos (bool, char, string, int, float, etc), listas, tuplas e funções. 3. Conceitos Básicos de Haskell - Parte 1 Possui uma variável de tipo que possibilita o polimorfismo. Suas funções podem utilizar uma cláusula where para passos intermediários. Possui condicionais (if-then-else ou guards). Também pode escrever expressões lambdas. Possui listas de valores de mesmo tipo que podem ser infinitas por ser uma promessa, e conta com operações e recursão sobre as listas.
13 BRUNO STORER FRANCO MARTINS Calculo Lambda: Elementos: 1- Variaveis (compostas de letras) 2- Definições de funções (em haskell sendo \ utilizado para declarar funções) 3- Aplicações de funções Em sua sintaxe original a letra grega lambda era utilizada para definir funções. Syntatic sugar -> Uso de sintaxe que não agrega em poder de expressão, apenas facilita escrita. Expemplo: \x -> \y -> e pode ser escrito como \x y -> e Escopo->Indica a visibilidade de uma váriavel. Variavies livres-> aquelas que não estão presas ao escopo de uma função. Expressão fechada-> expressão sem variaveis livres . Redução alfa-> renomear um parametro formal. Redução beta-> aplicar uma expressão utilizando uma váriavel livre (aplica uma função). A aplicação de uma função é o exemplo de uma redução beta. Exemplo: (\f -> f y) k => k y Expressões em que não podemos aplicar reduções betas se encontram na forma normal Exemplo: x y (veja que x é uma função que não esta ligada a nada, não há como beta-reduzir) Expressões boleanas podem ser representadas apenas com funções. Verdadeiro = \x y -> x Falso = \x y -> y IF = \b x y -> b x y Operações lógicas também possuem funções equivalentes no cálculo lambda. Tuplas também podem ser usadas através de funções: PAIR = \x y -> (\b -> IF b x y) (utilizado para gerar a tupla) FISRT = \p -> p Verdadeiro (utilizado para coletar primeiro elemento da tupla) SECOND = \p -> p Falso (utilizado para coletar segundo elemento da tupla) Numeros de Church define os naturais de forma que o número X é representado como a chamada de uma função f chamada X vezes. Com isso operações matematicas podem ser definidas: INCREMENTO = \n -> \f x -> f (n f x) ADD = \n m -> n INCREMENTO m De forma semelhantes de mais operações podem ser modeladas com funções. Ponto fixo de uma função é um valor que dado como entrada de uma função o retorno da mesma é o valor inalterado. Sendo assim se definirmos A = (\x -> f(x x)) (\x -> f(x x)) veja que A = (\x -> f(x x)) (\x -> f(x x)) = f (\x -> f(x x)) (\x -> f(x x)) = f a, ou seja, A é ponto fixo de qualquer função f. O combinador Y é definido como Y = \f->A, ou seja, dado uma função Y retorna um ponto fixo da função. Agora funções recursivas se tornam possiveis, dado uma função f, desejada ter comportamento recursivo, sendo aplicada no elemento e podemos então escrever isso como Y f e.
14 CAIO ARGENTINO DE OLIVEIRA
10 CAIO HENRIQUE DOS SANTOS RIBEIRO
50 CARLOS EDUARDO DE ABREU BATISTA
15 DANIEL ESPINDOLA DA SILVA Haskell Básico: Tipos básicos: Bool representa verdadeiro ou falso. Char representar caracteres String: É uma sequência de caracteres que pode ser criada usando aspas duplas, internamente é equivalente a uma lista de Char Int: Inteiro com precisão fixa Integer: Inteiro com precisão arbitrária porém menos eficiente. Float: Valores de ponto fluente Double: Valores de ponto fluante com maior precisão Listas: Conjunto de elementos do mesmo tipo, não tem tamanho determinado e funcionam de maneira similar a uma lista ligada, de modo que os acessos ocorrem em tempo linear. Tuplas: Conjunto de elementos com tamanho determinado, tipos não precisam ser os mesmos. Assinatura de Funções: São declarações que vão acima das funções e definem os tipos dos parâmetros e do retorno, em alguns casos podem ser autodeterminadas pelo próprio Haskell. Guard Clauses: Servem pra simplificar a escrita de partes de funções que exigiriam uma sequência de condicionais
17 DIEGO SOUSA SANTOS Playlist 2: Foram explicados o contexto histório e o conceito de cálculo lamba, bem como suas aplicações em Haskell através de recursividade, combinador Y, etc.. Playlist 3: Introdução aos conceitos básicos de haskell. Nesse módulo vimos os seguintes conceitos: -Contexto histório -Haskell possui códigos concisos e declarativos, sendo que o programador declara o que ele quer ao invés de escrever um passo-a-passo -Haskell trabalha com imutabilidade, não existindo conceito de variável. Como consequência disso, não existem laços de repetição também. Ao invés disso usamos recursividade -A avaliação preguiçosa está presente em haskell. O resultado de uma função só é computado quando requisitado. Vimos também os seguintes comandos: -Stack run, para compilar e rodar os programas -Stack build, para compilar os programas -Stack ghci, para utilizar o compilador no terminal Em relação à sintaxes e à linguagem, vimos: -Declaração de funções -Condicionais -Nomenclatura de funções e argumentos -Regras de layout -Comentários -Tipos de dados básicos -Tuplas e listas Além de explorar através de exercícios algumas propriedades e métodos que se relacionam aos tipos de dados
87 DIOGO AKIO BALBONI MIYAKE Foi apresentado sobre Overload Types, Exemplos de Funções, Clausula Where, Condicionais, Guard Expressions, Pattern Matching, Expressões Lambda, operadores, Listas, list compreenssion, Funções para trabalhar com listas. Foi mostrado que em list compreenssion temos 4 partes, como Assinatura, parametros, gerador e guard. Exemplo: primos :: Int -> [Int] primos n = [x | x <- [1..n], primo x] Foi mostrado a facilidade em usar recursão em algumas funções pra solucionar alguns problemas. Exemplo: fatorial :: Integer -> Integer fatorial 0 = 1 fatorial 1 = 1 fatorial n = n * fatorial (n-1) > fatorial 4 => 4 * fatorial 3 => 4 * (3 * fatorial 2) => 4 * (3 * (2 * fatorial 1)) => 4 * (3 * (2 * 1)) => 4 * (3 * 2) => 4 * 6 => 24
19 EDUARDO AKIRA UENO Calculo lambda: descreve computação utilizando funções. É composta de 3 elemetnos: variáveis, definições e aplicações. Programação em Haskell tem como características códigos concisos e declarativos, imutabilidade, utilização de funções recursivas, funções de alta ordem, ou seja, que podem receber outras funções como parametros, tipos polimórficos e utilização de avaliação preguiçosa, como visto na ultima semana. Uma das principais estruturas da linguagem funcional é a lista: representação de valores de um determinado tipo, onde todos os valores contidos na lista devem ser do mesmo tipo. Conjuntos: podemos utilizar o haskell para declarar conjuntos como uma sintaxe muito parecida de matemática, por exeplo: [x^2 | x <- [1..5]] que é o mesmo que: {x^2∣x∈{1..5}}
52 EDUARDO ALVES FERREIRA JUNIOR Cálculo lambda: -Tudo que é calculável/computável pode ser calculado pelo cálculo lambda e computável pela máquina de Turing; -Descreve computação utilizando apenas funções; -Composto por variáveis, definição e aplicação de funções; -Sintaxe: Variável: x, y, z etc Abstração: \x -> e (onde x é o parâmetro e "e" é o corpo da função); Aplicação: e1 e2 (aplique o argumento e2 na função e1); Para funções com mais de um parâmetro utiliza-se encadeamento de funções; Qualquer x no escopo (e) é ligado por \x. Variáveis não ligadas são livres; Funções sem variáveis livres são funções fechadas (combinadores). -Semântica: Passo/redução alpha: renomeia todas as ocorrências de um parâmetro; Passo/redução beta: chama a função (substituição das ocorrências de parâmetros do corpo da função); Forma normal: Impossível aplicar mais reduções; Avaliação: Reduz até chegar na forma normal Combinador ômega: (\x -> x x) (\x -> x x) nunca chega à forma padrão. Para modelar recursão utiliza-se o Combinador Y. Haskell: -Códigos concisos e declarativos; -Imutabilidade ("variáveis" não variam); -Funções recursivas (sem laços); -Funções de Alta Ordem (podem receber funções como parâmetro); -Tipos polimórficos; -Avaliação preguiçosa; -Precedência: Funções > Operadores; -Blocos definidos por identação (usar espaços); -Definição: v :: T; -Verificar tipo: ":t expressão/variável"; -Listas contém elementos do mesmo tipo; -Tuplas são finitas e contém tipos diferentes; -Funções recebem "Algo" e retornam "AlgumaCoisa": f :: Algo -> AlgumaCoisa; -Classe de Tipos = Conjunto de Tipos; -Instância de Tipo = Pertence a um Conjunto de Tipos; -Atentar-se às funções prefixas e infixas; -Assinaturas de funções são fundamentais; -Expressões lambdas (funções anônimas, não nomeadas); -Listas podem ser infinitas ex [1..]; -Operações Listas: !!, tail, head, take, drop, length, sum, product, zip; -Compreensão de Listas (como python); -Utilizar recursão em vez de laços (percorrer listas etc) -stack ghci para abrir o interpretador.
20 EDUARDO MACIEL DE SOUZA Nessa semana estudamos sobre funções lambda e tivemos uma introdução a linguagem Haskell. O sistema lambda é capaz de descrever a computação através de funções, o que é muito útil para estudos na área da computabilidade. Esse sistema usa apenas 3 elementos para representar uma função (variáveis, atribuição e substituição). Aprendemos sobre a representação de funções lambda e seus usos no Haskell. Vimos também alguns tópicos importantes sobre a linguagem, como: Tipagem, polimorfismo, declaração de funções, atribuição de variáveis e a imutabilidade, classes de tipo, açucar sintático, escopo, redução beta e forma normal, tipos de dados, recursão e compreensão de listas. Com o aprendizado desses conceitos podemos entender como que algoritmos imperativos podem ser implementados sem o uso de laços ou variáveis mutáveis, o que nos faz entender as soluções através do paradigma funcional. Uma vez que que os métodos citados são substituidos por recursões e substituições em estruturas que estão muito mais próximas da linguagem matemática. Nos exercícios práticos, tivemos que estabelecer tipos corretos para as variáveis de diversas funções, usar recursão, "pattern matching", encadeamento de funções e compreensão de listas.
23 EUGENIO VERAS MARIA Estava tentando definir as assinaturas como, por exemplo, Integer a => a -> a -> a, entendi que isso nao funciona, funcionaria se declarasse 'a' como Num, mas nao entendi o porque disso velocidade - Creio que exista erro aqui, o texto do enunciado não condiz com o texto comparativo no teste Tive dificuldade de entender como converter Double para String, nao sei se com "show" seja o melhor metodo Entendo que a entrada da funcao deva ser Float, pois a saida nos testes requer Float somaEhMult7 - Consegui usar uma funcao dentro de outra, achei interessante a forma que isso acontece ...NoIntervalo - Entendo melhor o uso de recursao para simular um loop procuraSeis - Tentei expressar a ideia, o codigo nao carrega bem, nao sei se algo esta fazendo encher a memoria
24 FABIO DOS SANTOS DE SOUZA Nessa segunda semana da disciplina de paradigmas de programação, iniciamos nossos estudos encarando um modelo de computação conhecido como cálculo lambda, criado por Alonzo Church, em sua busca por formalizar que tipos de problemas seriam computáveis. O paradigma de Alonzo se baseia unicamente em operações simples sob funções, porém, demonstra o mesmo poder de uma máquina de Turing. Fomos iniciados na sintaxe desse modelo e construímos diversas funções simples a partir disso. Exploramos o escopo de variáveis e também aprendemos sobre syntax sugar, e sobre como reduzir expressões lambdas, utilizando-se de 2 regras, denominadas respectivamente de passo alpha e passo beta; as reduções são de fundamental importância, pois, elas avaliam as expressões lambda e as classificam nas que podem e que não podem ser avaliadas. Depois da introdução ao cálculo lambda, vimos a construção das estruturas fundamentais em programação ( if, else, boolean, inteiros, struct e etc ) a partir das expressões lambda. Além disso, aprendemos como a recursão é implementada no cálculo lambda, já que não existem laços de repetição nesse modelo; conhecemos o operador Y, que foi criado a partir do combinador Omega, e nos permite avaliar uma expressão lambda indefinidamente, sendo fundamental para a recursão. Em seguida, fomos introduzidos na sintaxe do haskell, passando por diversos conceitos básicos como: nome de variáveis aceitos, regras de layout, como definir funções e assinaturas para funções e etc. Aprendemos também a usar o ghci, um interpretador de haskell, para nos auxiliar na exploração de tipos básicos do haskell. Ademais, conhecemos os tipos mais fundamentais dessa linguagem, que são : Bool, Int, Integer, Float, Double, Tuple , List e etc. Vimos que haskell é uma linguagem com tipagem forte, e ainda assim polimórfica; ao final dessa semana aprendemos a manipular os tipos de dados mais básicos do haskell.
25 FELIPE ASSIS Calculo Lambda é uma forma de implementar logica matemática para definir funções que utilizam termos lambda o que permite expressar a logicas e matemática, o que é muito útil pelo fato de sermos capazes de utilizar de expressões matemáticas direto no código o que no caso do Haskell torna as expressões mais curtas que nas demais linguagens. Outra peculiaridade do Haskell é que uma vez declarada um valor para um termo está é imutável. Para Haskell uma das coisas mais incríveis é que por ter uma avaliação preguiçosa temos a capacidade de utilizar expressões que utilizam de listas infinitas das quais só serão utilizadas caso o codigo exija e quando exigir.
71 FELIPE AUGUSTO FLOR DE SOUZA Haskell: Surgiu como linguagem de pesquisa; Hoje usado por várias empresas; Características: Códigos curtos e declarativos; Imutabilidade(Enxergar como equação) Funções recursivas (Não tem laço); IMPORTANTE: USAR ESPAÇO; Conceito básicos: .yml contém as infos das bibliotecas e a versão. Stack build <- compila
26 FELIPE DIAS CORREIA
70 FELIPE MOREIRA TEMOTEO DA SILVA -Cálculo λ nada mais é do que sistema formal para expressar computação baseado em abstração de funções e aplicação usando apenas atribuições de nomes e substituições. -Existem alguns problemas associados a ele como: Decisão; Função; Busca; Otimização. E o cálculo λ descreve computação apenas utilizando funções. -A sintaxe do cálculo λ é composta de 3 elementos, sendo eles: Variáveis; Definição de funções; Aplicação de funções. -Um programa é definido por uma expressão “e”, ou termos -λ que podem assumir uma de três formas: Variável; Abstração; Aplicação. -Se “e” não tem variáveis livres, então e é uma expressão fechada (combinadores) -Toda expressão pode ser reescrita utilizando 2 tipos de regras: Passo α; Passo β. -Um termo está em sua forma normal se não contém nenhum redex (expressão redutível). - Combinador Ω: É impossível chegar na forma normal. -Combinador Y: escreve uma expressão λ cuja avaliação se repete indefinidamente, tal qual o combinador Ω, mas que diferentemente deste faz algo útil durante cada redução: a avaliação da função f. -O Haskell tem algumas características como: Códigos concisos e declarativos; Imutabilidade; Funções recursivas; Funções de alta ordem; Tipo polimórficos; Avaliação Preguiçosa. - Um tipo é uma coleção de valores relacionados entre si. E em Haskell temos os seguintes tipos: Bool; Char; String; Int; Integer; Float; Double. -Do mesmo jeito que em outras linguagens em Haskell temos listas, tuplas e funções. -Restrição de classe: ideia de que uma função pode ser aplicada apenas a uma classe de tipos. - Expressões guardadas nada mais é do que Uma alternativa ao uso de if-then-else usando “|”. -As expressões lambdas, também chamadas de funções anônimas, definem uma função sem nome para uso geral -Expressão geradora: gera valores na sequência conforme eles forem requisitados.
27 FELIPE PONSANO FRANKE
36 GABRIEL ALBANO SANTOS
37 GABRIEL BELLOMI MEALE Computabilidade é uma área de estudo central da Ciência da Computação. Ela estuda se é possível ou não de um dado problema ser solucionado, computacionalmente, com um algoritmo. A formalização do que é ou não computável foi dada por Church e Alan Turing que, de formas diferentes, chegaram a mesma conclusão do que é ou não computável. Para Turing, um problema é solúvel mecanicamente se existe uma Máquina de Turing que resolve aquele problema, e demonstra que existe pelo menos um problema insolúvel algoritmicamente. Church, utilizou um sistema formal para expressar computação baseado em abstração de funções e aplicação usando apenas atribuições de nomes e substituições. No caso, tudo que é efetivamente calculado pelo cálculo lambda, é computável numa máquina universal de Turing. Synthatic Sugar - formas de escrita que não mudam nada o poder da linguagem mas que facilita a organização e escrita do código. Escopo de variáveis - O escopo de uma variável indica a visibilidade de uma variável para uma função. Um combinador é uma expressão lambda que não tem variáveis livres e é uma expressão fechada. Semântica especifica o significado (ou comportamento), descrevendo as estruturas de uma linguagem de programação. Redução alpha: renomeia um parâmetro formal Redução beta: aplica uma expressão utilizando um variável livre (ou de maneira mais simples, chama uma função) Forma normal é a qual não contém nenhum redex (termo na forma (\x -> e1) e2) Avaliação - aplicação de reduções betas e alfas até se encontrar numa forma normal. Non-Terminanting Evaluation - A cada aplicação de redução, retornamos as mesmas expressões iniciais. (combinador ômega)
30 GABRIEL DE MELLO FIALI Apresentação dos conceitos sobre o Cálculo $\lambda$ e a questão de como definir o que é computável ou não, discutida pelos matemáticos Alan M. Turing e Alonzo Church. Alguns problemas associados são: decisão, função, busca e otimização. Cálculo lambda: permite desenvolver uma linguagem de programação com o uso exclusivo de funções. Composto por variáveis, definição de funções e aplicação de funções. Programas se definem como uma expressão ou termos que se apresentam como variáveis (nome que assume valor), abstrações (contam com um parâmetro formal e um corpo da função) ou aplicações (contam com função e argumento). A definição de mais de um argumento implica no uso de um encadeamento de funções. Logo, só possuem um valor de retorno. Ao mesmo tempo, seus escopos se restringem ao conteúdo de uma abstração, com um elemento estando livre caso não esteja dentro da mesma. Uma expressão sem variáveis livres define uma expressão fechada. A Semântica é definida em 2 passos, alfa (corresponde à renomeação de parâmetros formais) e beta (aplicação de uma expressão com variável livre, que dá base para a computação por substituição e busca). A avaliação de uma expressão é feita aplicando reduções alfa e beta sucessivas até que se encontre na forma normal, sem poder ser reduzida novamente. Combinadores ômega não conseguem chegar a uma forma normal, com reduções beta que não geram mudanças (avaliação infinita). Combinadores Y se aproveitam do mesmo para definir um comportamento análogo ao de laços, via recursividade. Haskell: códigos concisos e declarativos, sem a presença de variáveis e sim nomes e declarações (imutáveis). Não permite laços de repetição, utilizando funções recursivas em seu lugar. Permite funções de alta ordem, que podem receber outras funções como parâmetros, e tipos polimórficos, cujo retorno não depende do tipo dos elementos manuseados. Computa resultados de funções apenas quando requisitados (avaliação preguiçosa). Introdução da programação em Haskell e suas particularidades: - Tipagem forte - Cláusula where - Notação guard - Underscores - Listas - Funções !!, head, tail, take, length, sum, product, drop, concat, zip. - Algumas operações podem ser computadas sobre listas infinitas devido à avaliação preguiçosa. - Compreensão de listas: resultado final, expressão geradora e filtro. Útil para refletir o comportamento de laços com várias camadas, função length, etc. - Recursividade
34 GABRIEL MENDONÇA FARIAS Na semana 2 nos foram apresentados conceitos de programação com relação ao calculo lambda, que é baseado em abstração de funções utilizando atribuições e substituições. Este tipo de calculo é utilizado para resolver problemas como decisão, função (matemática), busca e otimização de sistemas. De modo que esta forma de programar, utiliza-se apenas de funções para resolver os problemas propostos. O calculo lambda é baseado em variáveis (que assumirão um valor durante a computação), definição das funções (abstração ou função lambda) e aplicação das funções (a chamada realizada para para executar a função). Na definição de funções lambda, é utilizado o símbolo λ, que é substituído por \, bem como . é substituído por →. Booleanos em calculo lambda é baseado na verificação de se uma função retorna determinado valor, verificando se aquela operação esperada é verdadeira, ou não. Registros são circunstâncias em que se da entrada de uma certa quantidade de valores e seu retorno, que pode ser feito utilizando uma função que receba dois valores e retorne ambos, um, ou outro, por exemplo. O combinador Y se trata da utilização do retorno de um ponto fixo em funções lambda, a fim de realizar tarefas que exijam recursão, por exemplo. Deste modo, é possível, por exemplo, a cada vez que o valor fixo é retornado, uma nova função lambda realize uma nova tarefa com o valor selecionado. Também é possível fazer que funções recebam funções como parâmetros Haskell também utiliza suas funções de modo que apenas sejam calculadas quando seu resultado for exigido dentro do programa. Para programar as funções em Haskell, é necessário escrever o nome da função, seguido pelos parâmetros e a aplicação e seus códigos é definida por indentação. As assinaturas estão associadas ao cálculo lambda e mostram qual tipo de valor está compondo a função.
35 GABRIEL MURAKAMI ALVES
42 GABRIEL RIOS SOUZA Computabilidade/Computação: estuda/mostra quais problemas podem ou não serem resolvidos por meio de algoritmos Cálculo Lambda (λ): - Criado por Alonzo Church na década de 1930. - Sistema formal para expressar computação baseado em abstração de funções e aplicação usando apenas atribuições de nomes e substituições. - Para programar apenas precisamos de funções e é apenas isso que o cálculo lambda utiliza para descrever computação. Sintaxe do Cálculo λ: - Composto de 3 Elementos: - Variáveis - Definição de Funções - Aplicação de Funções - Um programa é definido por uma expresão 'e' ou termos-λ: e ::= x (Variavel) | \x -> e (Abstração/Função λ/Função Anônima) | e1 e2 (Aplicação -> e1(e2)) - Podemos representar todas as funcionalidades de Linguagens reais usando λ (Booleanos, Registros, Números, Funções, Recursão) Introdução ao Haskell: - Características: - Códigos concisos e declarativos - Imutabilidade (Não há Variáveis) - Funções Recursivas (Não há laços de Repetição) - Funções de alta ordem (Funções que recebem funções como parâmetro) - Tipos polimórficos (Funções genéricas -> Classes de Tipos) - Avaliação preguiçosa - Funções: nome da função seguida dos parâmetros separados por espaço (Tem maior precedência). f a b + c*d -- f(a,b) + c*d - Convenções: - Nomes utilizam camelCase. - Nomes reservados não podem ser utilizados. - Listas são nomeadas acrescentando um 's' ao seu nome. - Blocos lógicos são definidos pela identação. - Utilizar Espaço ao Invés de Tab. - Comentários são feitos com -- ou {- -} - Tipos de Dados: - Bool (True/False) - Char (Unicode -> Aspas Simples) - String (Aspas Duplas) - Int (−2^63 até 2^63 − 1) - Integer (Inteiros de precisão arbitrária -> Int é mais rápido) - Float (7 Digitos) - Double (16 Digitos) - Utiliza '::' para Definição de Tipos: False :: Bool 10 :: Int - Listas: [1,2,3,4] :: [Int] ['o', 'l', 'a'] :: [Char] - Tuplas: (1.0, "Sim", False) :: (Double, String, Bool) - Funções: soma :: Int -> Int -> Int soma x y = x + y mult :: Int -> Int -> Int -> Int mult x y z = x * y * z
33 GABRIEL ROSSETTO MIGLIORINI Haskell é uma linguagem puramente funcional. O código é conciso e declarativo. As variáveis em haskell são imutáveis, assim, torna-se impossível criar uma estrutura de looping for - uma vez que alteramos o valor da variável iterativa. Os tipos básicos em haskell são: Bool, Char, String, Int, Integer, Float e Double. O primeiro tipo contém os valores True e False - e pode ser recombinado logicamente com uso de && (AND), || (OR) e not. Já o tipo char contém todos caracteres no sistema Unicode. Ao passo que a sequência de caracteres é representada pelo tipo String. Os tipos Int e Integer contemplam números inteiros, onde o primeiro possui precisão de 64bits enquanto o segundo possui precisão arbitrária. De modo quase análogo temos os tipo Float e Double, que representam números reais com precisão simples e dupla - respectivamente. A atribuição de um tipo a uma variável pode ser feita com o uso de '::'. Assim, é possível, por exemplo, expressar o número como Float '3.0 :: Float' ou Double '3.0 :: Double'. Para verificar o tipo de algo desejado, dentro do ghci, basta digitar ':t <algo>'. O interpretador irá retornar de 'algo' é um tipo estrito (como os já exemplificados) ou um tipo genérico (caso não tenhamos definido e exista ambiguidade).
80 GABRIEL SILVESTRE MANCINI
40 GEORGE HARRISON ROCHA Na semana 2 os professores introduziram o conceito de cálculo lambda, que é um sistema formal para expressar computação baseada em abstração de funções e aplicações usando apenas atribuições de nomes e substituições. A linguagem Haskell possui as seguintes características: - Códigos concisos e declarativos; - Imutabilidade; - Funções Recursivas; - Funções de alta ordem; - Tipos polimórficos; - Avaliação preguiçosa. Aprendemos sobre convenções, assinatura de funções e vimos os tipos de dados suportados nativamente pela linguagem Haskell, tais como Bool, Char, String, Int, Integer, Float, Double, Listas, Tuplas e Funções. Para organizar o nosso código em Haskell, podemos usar a cláusula where para definir nomes. Para condicional em Haskell, temos o if-then-else (também presentes em algumas outras linguagens) e também temos os Guard Expressions. Temos também as expressões lambdas, também chamadas de funções anônimas, que definem uma função sem nome para uso geral. Na aula de listas aprendemos como criá-las, funções para manipular listas, compreensão de listas. Em Haskell, usamos recursão para fazer laços de repetição.
41 GIANCARLO KAMI DELL ARINGA VIANA Nesta semana os diversos tipos de dados foram introduzidos. Tambem foram introduzidas listas e como manipula-las Por fim, foi introduzido o conceito de recursao em haskell. Os exercicios da semana foram mais complexos, e tive problemas com os caracteres acentuados e o simbolo ∈, que acabei substituindo.
94 GIOVANNA NOGUEIRA Cálculo Lambda: • Sistema usado para expressar computação baseado em funções e aplicado usando atribuições e substituições; • É possível realizar atribuição, laços, recursão, etc., apenas com o uso de funções; • Sua sintaxe é composta por 3 elementos: variáveis, definição de funções e a aplicação de funções; • Synthatic Sugar é um recurso da sintaxe que pode ser usado para simplificar o código, facilitando sua visualização; • Uma expressão fechada, ou combinador, é uma expressão sem variáveis livres; • O combinador Y nos permite escrever uma expressão λ cuja avaliação se repete indefinidamente, avaliando a função a cada redução. Conceitos Básicos: • Haskell tem como características códigos concisos e declarativos, imutabilidade, funções recursivas, de alta ordem, tipos polimórficos e avaliação preguiçosa; • As funções são escritas como o nome da função + os parâmetros; • Um tipo é uma coleção de valores relacionados entre si, como Integer, Bool, Char, Float, etc.; • Listas são sequências de elementos do mesmo tipo agrupados por colchetes e separados por vírgula; para sua manipulação, podemos utilizar as funções “!!”, head, tail, take, drop, lenght, sum, product, “++” e “:”; • Tuplas são sequências finitas de componentes, contendo zero ou mais tipos diferentes; • Funções são mapas de argumentos de um tipo para resultados em outro tipo, quando ela só pode ser aplicada a uma única classe de tipos é explicitada pela Restrição de Classe; • a é conhecida como variável de tipo e ela indica que a função deve funcionar para qualquer tipo de dado; • A cláusula where define nomes intermediários; • A função if-then-else permite utilizar desvios condicionais; • Expressões lambdas (funções anônimas) definem uma função sem nome para uso geral; • Podemos usar recursão nas listas para trabalhar individualmente com cada elemento.
39 GIOVANNI ALMEIDA DE SOUSA Semana 2 - Paradigmas de Programação 1. Cálculo λ: a. Alan Turing e Alonzo Church (orientador de doutorado de Turing) definiram a computabilidade (Turing) ou o cálculo λ de forma equivalente e contemporaneamente. b. Pode ser definido como um sistema formal para expressar computação baseado na abstração de funções e aplicação usando apenas atribuições de nomes e substituições. c. Descreve computação apenas utilizando funções. Sua sintaxe é composta por três elementos: variáveis, definição de funções e aplicação de funções. A semântica é composta por α e β. α renomeia um parâmetro, enquanto β chama uma função. d. O Combinador Ω permite que seja escrito um programa que a cada redução β o resultado seja ele próprio. e. O Combinador Y permite que uma função lambda se repita indefinidamente, assim como o Combinador Ω. A diferença é que para cada redução, ocorre a avaliação da função f. Isso só é possível pelo uso dos pontos fixos, pois assim podemos trocar A por f(A) a qualquer momento. 2. Introdução ao Haskell a. A linguagem possui códigos concisos e declarativos. b. Possui o conceito de imutabilidade: as variáveis na verdade são nomes e declarações, não podendo receber novas atribuições. c. Não existem laços, apenas funções recursivas, afinal os laços atribuem novos valores para a mesma variável. d. Funções de alta ordem: funções podem receber outras funções como parâmetros. e. Permite tipos polimórficos: funções genéricas que funcionam para classes de tipos. f. Avaliação preguiçosa: a função só será avaliada quando for solicitada, o que permite a criação de listas infinitas, por exemplo. g. Exemplo de função em Haskell: i. Multiplicar :: Int -> Int -> Int --assinatura: a função recebe dois inteiros e devolve um inteiro. ii. Multiplicar x y = x * y
43 GIULIA RIBEIRO DE CARVALHO
46 GUILHERME FERREIRA GALDINO O cálculo lambda se baseia em expressar a computação em funções utilizando apenas atribuições de nomes e substituições. Nele dois pontos devem ser considerados: a sintaxe e a semântica. Na sintaxe, existe três elementos: variáveis, definição de funções e aplicação de funções. As variáveis é apenas um nome que assumirá um valor durante a computação. A definição de funções ou a abstração da função é formada por duas partes: parâmetro formal e o corpo da função, seguindo o determinado formato \x -> e, em que para qualquer valor de x será computado e. Por último, a aplicação da função segue a seguinte forma e1 e2, que significa que a aplicação da função e1 utilizará e2 como argumento. Outro ponto é o escopo das variáveis, em que dado a definição de uma função \x -> e, a expressão 'e' é o escopo de x, assim qualquer ocorrência de x em 'e' está ligada ou bound por \x. Portanto, se x não está dentro de uma abstração, quer dizer que x está livre ou free. Assim, se a expressão não possui variáveis livres são chamadas de expressões fechadas ou Combinators. Na parte da semântica existe duas regras: Equivalência alfa e a Redução beta. A equivalência alfa apenas renomeia o parâmetro formal para evitar conflito de nomes. A Redução beta aplica uma expressão utilizando uma variável livre, em que substituirá todas as ocorrências do parâmetro formal. Assim, ao reduzir o máximo possível da função, ela chegará em sua forma normal. Porém, existem casos que não estará na forma normal e, mesmo assim, não será possível reduzi-la, ou seja, existe um Non-Terminating Evaluation, conhecidos também como Omega Combinator, no qual possuem a seguinte estrutura (\x -> x x) (\x -> x x). Por fim, temos o combinador Y, que é semelhante ao combinador Omega, porém realiza algo útil durante suas reduções. A diferença está na utlização do ponto fixo nas funções lambdas. Ponto fixo é um elemento do domínio da função que é mapeado para si mesmo, ou seja, dado um p e uma função func, temos a seguinte equivalência p ⇔ func p. Portanto, é possível trocar uma expressão que contém apenas p por uma que avalia func que contém p.
47 GUILHERME FUZISAWA DE SA Tipos e Classes Tipos Básicos: Bool, Char, String, Int, Integer, Float e Double Listas: Sequência de elementos de um mesmo tipo. Exemplo: ['o', 'l', 'á'] :: Char Tipos de funções: Ṕodemos ter funções com tipos primitivos ou tipo Polimorfos, onde determinada função aceita diversos tipos. Por exemplo: função length, esta calcula o tamanho de uma lista independente se essa lista é uma lista de Int, Float, Char etc. Tipos sobrecarregados: Funções deste tipo podem ser utilizadas para tipos pertencente "conjunto em comum". Por exemplo: (+) pode calcular a soma de numero do tipo float ou integer, ou de maneira geral... soma de valores que valores que pertencem ao tipo Núm. Definição de funções Podemos assinar nossas funções, ou seja, podemos definir de maneira rigorosa quais são os tipos dos parametros de entrada, sua saída ou podemos defini-las combinando funções existentes etc. Sintaxe de expressões condicionais: if condicional then true else false Outra alternativa as expressões condicionais são as Guard equations. Para escrever uma Guard equation utilizamos o operador pipe (|). Exemplo: myFunction | condicional = result | otherwise = otherResult Em cada pipe podemos definir uma condicional seguida do seu valor caso aquela expressão seja verdade. Por fim, definimos o pipe "otherwise" para os casos em que nenhuma das condições acima foram satisfeitas. Patter Matching: Outro recurso interessante, se o primeiro padrão coincide, então o primeiro resultado é escolhido. Exemplo: implementação função head(mostrado em aula) Funções Lambda: Funções anônimas onde não precisamos definir seu nome e o próprio corpo da função define como os argumentos serão tratados na função. Exemplo: \x -> x^2 List Comprehensions: É algo semelhante ao que temos na matemática e/ou Python. É uma maneira de iterar sobre listas. Além disso, falamos que alguns métodos de listas como head, tail, any, all e o operador bang bang (!) onde podemos selecionar um elemento de uma lista pelo índice.
48 GUSTAVO MATHEUS LIMA SANTOS O cálculo lambda é um sistema formal para expressar computação baseado em abstração de funções e aplicação usando apenas atribuições de nomes e substituições. Esse conceito foi concebido por Alonzo Church que era o orientador de Allan Turing. O interessante que as funções podem ser consideradas a menor linguagem universal, a partir delas é possível construir atribuições, tipos de dados, condicionais, laços, recursão, ponteiros, objetos e classes, ou seja, tudo que é necessário para se realizar computação. O haskell como linguagem puramente funcional apresenta características como códigos concisos e declarativos (o programador declara o que quer ao invés de definir uma sequência de passos), imutabilidade (não existem variáveis, apenas nomes e declarações), funções recursivas, funções de alta ordem (funções podem receber outras funções como parâmetros), tipos polimórficos (funções genéricas que funcionam para classes de tipos) e avaliação preguiçosa (o resultado é computado apenas quando necessário). Há convenções em Haskell, tais como: os nomes das funções e seus argumentos devem começar com uma letra minúscula seguida por 0 ou mais letras; não se pode utilizar nenhum dos nomes reservados; acrescenta-se um “s” ao nome de listas; os blocos lógicos são definidos pela identação. É possível utilizar a sintaxe do “where” para definir trechos de código e melhorar a leitura. O Haskell também apresenta tipos de dados como Listas (definidas entre “[]”) e tuplas (definidas entre “()”), é possível gerar uma lista de tuplas ou uma tupla de listas. Outra característica do Haskell é a possibilidade de utilizar o “|” (pipe) ao invés de repetir diversos “ifs”. Expressões lambda são funções anônimas e começam com uma barra invertida “\”, elas podem ser utilizadas em diversos trechos do código, inclusive em compreensão de listas que é um feature que aplica um comando a uma lista inteira.
38 GaMendes Nessa segunda semana de curso, fomos introduzidos ao cálculo lambda, que assim como o modelo computacional criado por Alan Turing, que consistia de uma máquina de estados finita cuja entrada é provida por uma fita de execução de tamanho arbitrário, estuda a computabilidade de problemas seguindo determinados algoritmos. O cálculo lambda, criado por Alonzo Church na década de 30, trata-se de um sistema formal para expressar computação baseado em abstração de funções e aplicação usando apenas atribuições de nomes e substituições. Nessa parte foi ensinado como reconstruir utilizando funções construídas com base nos conceitos do cálculo lambda, as principais estruturas encontradas em linguagens que seguem outros paradigmas, como por exemplo Booleanos, Registros (structs, tuplas, …), Números e Recursão. Aqui também vimos o YCombinator, que nos permite escrever uma expressão lambda cuja avaliação se repete indefinidamente, tal qual o combinador omega, mas que diferentemente deste, faz algo útil durante cada redução: a avaliação da função f. Também tivemos uma introdução a linguagem de programação Haskell que por muito tempo foi considerada uma linguagem acadêmica. Aqui foram apresentadas as principais características da linguagem, como que ela é imutável, utilizada o conceito de recursão, visto que com a imutabilidade loops se tornam inviáveis, funções de alta ordem (funções que recebem outras funções como parâmetros), tipos polimórficos e avaliação preguiçosa. A partir daí, vimos como manipular e usar diversos tipos presentes na linguagem, como listas, inteiros, Strings, Doubles, etc., discutimos tabs e espaços, vantagens e desvantagens de cada um, polimorfismo e overloading de tipos. Aprendemos sobre condicionais e expressões guardadas, passamos por expression matching e finalizamos a semana utilizando esses conceitos, juntamente com recursão em listas.
51 HEBER CAMACHO DESTERRO
9 HEITOR BELLINI
49 HENRIQUE AUGUSTO DE OLIVEIRA No passado, haviam grandes discussões do que significa algo ser computável. A computabilidade estuda a possibilidade de um problema ser resolvido por um algoritmo. Com base em estudos de Church e Turing, foi verificado que tudo que é computado em uma Máquina de Turing é calculado usando Cálculo Lambda, que é utilizado para expressar computação com abstração de funções, atribuições e substituições. Existem muitos recursos na programação, mas o Cálculo Lambda descreve computação apenas com funções. Para aplicar os conhecimentos adquiridos, será usado a linguagem Haskell, que foi criada com o intuito de ser a primeira linguagem puramente funcional. Haskell tem características de de códigos concisos e declarativos, Imutabilidade, Recursividade, Função de Alta Ordem, Polimorfismo e uso de Avaliação Preguiçosa. Algumas convenções devem ser seguidas nas escritas de código. Funções devem começar com letra minúscula e não devem utilizar palavra reservada. O padrão de nome de listas são terminados em "s", sendo agrupados em colchetes e a identação é importante para identificar um trecho de código subordinado a um bloco superior. Em Haskell, os tipos são bem definidos. Para uma determinada função, a mesma pode apresentar um comportamento diferente para tipos distintos, que é o conceito de Overloaded Types. Na linguagem, é possível fazer condicional com if-then-else e através do Pipe, que define uma Guard Expression. Lembrando que, nesse último caso, é necessário utilizar a palavra "otherwise" quando a condição não é atendida. Conforme já citado, listas são definidas entre colchetes e possuem uma coleção de valores de um mesmo tipo. Algumas funções são úteis para manipular essas listas, como tail, head, take, drop e outros recursos. Uma outra característica é a recursão que, no Haskell, a avaliação é feita por substituições até que o resultado possa ser retornado nas chamadas da função.
54 HENRIQUE FANTATO SILVA DE ALBUQUERQUE Cálculo lamba, um sistema formal para expressar-se em computação, usando abstração de funções, atribuições e substituições, usando o mínimo possível para programar, sendo a menor linguagem universal. É composto de variáveis(nome que assumirá um valor durante a computação), definição de funções e aplicação de funções. Com isso em mãos, podemos representar computacionalmente tudo, desde números, a booleanos e funções. Para realizarmos recursões, precisamos utilizar o combinador Y, que devolve um ponto fixo para qualquer função lamba, e nos permite realizar uma avaliação da função a cada iteração. Haskell é a primeira linguagem puramente funcional, que por muito tempo era uma linguagem acadêmica, mas hoje é utilizada em diversas empresas. Como características, o Haskell possui códigos concisos e declarativos(dizemos oque queremos, e não como queremos), "variáveis" imutáveis(uma vez que um nome é declarado com um valor, ele não pode ser modificado), funções recursivas, de alta ordem(funções que recebem funções como parâmetro) e avaliação preguiçosa(funções são computadas somente quando utilizadas). No mais, podemos utilizar em Haskell os tipos de dados que estamos acostumados, funções, operadores, if/else, etc. Com um destaque para os guards e pattern matching, onde podemos simplificar ainda mais nosso código ao invés de usar diversos if/else. Também temos list comprehension, onde podemos gerar listas diversas de uma forma bem concisa e facilitada.
108 HENRIQUE MAGRO DE SOUZA Alonzo Church propôs uma visão da computabilidade das expressões composta apenas por funções (Cálculo Lambda). Turing, por outro lado, seguiu sua abstração por meio da máquina de Turing e chegou na mesma conclusão: que todas as expressões computáveis podem ser representadas pelo Cálculo Lambda ou pela Máquina de Turing. Algumas definições: - Uma variável é ligada está ligada ao escopo de uma função. - Uma variável é livre quando não está ligada ao escopo de uma função. - Uma expressão é fechada quando não tem variáveis livres. - Expressões fechadas são também chamadas de combinadores (combinators) Recursos que as linguagens já oferecem aos usuários que podem ser definidas a partir do cálculo lambda: - Booleanos - Registros (structs, tuplas) - Números - Funções - Recursão Ferramentas para chegar nas funcionalidades - Alpha Redução: Renomeia um parâmetro formal. - Beta Redução: Aplica uma expressão utilizando uma variável livre. - Alguns truques. rs... Combinador Y Y = \f -> (\x -> f (x x)) (\x -> f (x x)) Y fat 3 = fat (Y fat) 3 - Gera um ponto fixo para qualquer função lambda. - Permite a recursão. Aprendi também sobre a sintaxe do Haskell e conceitos básicos, que foram utilizados nos exercícios. - Assinatura de Funções - Tipos - Compreensão de Listas - Guards - Etc...
55 IAN LACERDA DA SILVA
56 IGOR SAWAKI Na década de 1930, Alonzo Church abordou a questão da computabilidade por um caminho de abstração de funções, que deu origem ao cálculo-\. A linguagem do cálculo-\ pode ser dividida em sintaxe e semântica. Na sintaxe, que são as regras de escrita, o cálculo-\ possui três elementos: - variáveis: x; - definição de funções: \x -> x; - aplicação de funções: e1 e2. Uma variável x está ligada por \x se há ocorrência(s) dela no escopo de \x. Caso contrário, a variável é livre (não ocorre dentro do escopo). Se uma expressão não tem variáveis livres, então ela é dita fechada, também chamada de combinadores. Nas regras semãnticas, podemos reescrever as expressões usando duas regras: - passo/redução alfa: "renomear" as variáveis ligadas; - passo/redução beta: substituir as ocorrências livres pelo argumento, copiar o resto. Uma expressão que poder passar por redução beta é dita expressão redutível, ou redex. Uma expressão que não contém nenhum redex está na forma normal (não é possível fazer redução beta). A avaliação de uma expressão é uma sequência de reduções alfa e beta até chegar a uma expressão na forma normal. Programando com \ Através da utilização somente de funções, é possível implementar elementos típicos de outras linguagens como: booleanos (true, false, if, not, and, or), registros (tuplas), números (baseados nos números de Church) e operações aritméticas (incrementa, soma, etc) e recursão (combinador Y). No caso da recursão, é utilizado o combinador-Y. Este combinador possui uma expressão semelhante ao combinador omega (\f -> x x)(\f -> x x), que gera um ciclo infinito de avaliações. Para que haja uma chamada recursiva da função é necessária a utilização de um ponto fixo desta função, formando o combinador Y = \f -> (\x -> f (x x))(\x -> f (x x)). Em Haskell, o combinador pode ser escrito como y f = f (y f).
93 IVO VECELIC NETO Cálculo λ É uma logica matemática e computacional para definir funções, usando como linguagem termos lambda , onde podemos descrever diversão funções matemáticas e logicas, dentro dessas funções especiais que podem ser usadas para obter as bases para as uma linguagem moderna isso sendo muito útil para a linguagem haskell onde as funções são a base estrutural para rodar o programa , por esse motivo normalmente os códigos em haskell são menores que em outras linguagens , além disso dentro do haskell temos que as variáveis são imutáveis , uma vez declaradas não podem ser modificadas, da a possibilidade de funções chamarem funções , e funções de modificação de tipo, o haskell tem todos os operadores básicos matemáticos , e tem uma possibilidade incrível de criar listas infinitas , através da avaliação preguiçosa , gerando promessas para os próximos valores , existem inúmeras funções para listas em haskell dando possibilidades para trabalho com as mesmas, dentro do haskell trabalhar com recursividade , pois como ele não salva o estado da chamada recursiva em uma pilha , o que evita o estouro da pilha,
57 JANUSA MAIA DA SILVA Haskell – conceitos básicos Códigos curtos e declarativos, Imutabilidade, Funções recursivas, funções de alta ordem, tipos polimórficos, avaliação preguiçosa. A aplicação de funções tem maior precedência. Nomes de funções e seus argumentos devem começar em letra minúscula. Nomes reservados: case, class, data, default, deriving, do, else, foreign, if, import, in, infix, infixl, infixr, instance, let, module, newtype, of, then, type, Where. Blocos de códigos são delimitados pela indentação. Comentários de linha: -- , {- ....-} Tipos de dados: Int, Bool, Char, String, Integer, Float, Double Listas: [‘a’,’b’]. Não especifica tamanho. Elementos devem ser do mesmo tipo. Tupla: sequência finita, contendo tipos diferentes, especificados com tipos e tamanho. Não podem ter aridade 1. Funções: mapas de argumentos de um tipo para resultados em outro tipo. Os tipos são estritos e rígidos, não é possível, por exemplo, somar Int com Float. Para usar uma função prefixa de forma infixa e vice versa: mod 5 2 => 5 `mod` 2; 5 + 2 => (+) 5 2. Funções para listas: !! -> xs !! 1 => primeiro elemento da lista xs head -> primeiro tail -> lista sem o primeiro elemento take -> take 10 xs => 10 primeiros elementos da lista xs drop -> drop 10 xs => lista xs sem os 10 primeiros elementos length -> tamanho da lista sum -> soma dos elementos da lista product -> produto dos elementos da lista concat [[1,2,3], [6,7,8]] => [1,2,3,6,7,8] zip [1,2,3] “ola” => [(1,’o’), (2,’l’), (3,’a’)] pairs [1..5] => [(1,2), (2,3), (3,4), (4,5)] maxBound: valor máximo de um tipo. string com aspas duplas é um açúcar sintático para uma lista de caracteres. Compreensão de listas: [expressão | expressão geradora, filtro]: Ex.: Pares de 0 a 100 e múltiplos de 6 => [x | x <- [0, 2..100], x `mod` 6 == 0]
58 JEAN AUGUSTO DE ARAUJO Haskell nasceu para ser uma linguagem funcional inteiramente pura. Foi considerada uma linguagem acadêmica inicialmente, mas hoje é utilizada em empresas, por exemplo, pelo Facebook. Seus códigos são concisos e declarativos, fugindo do paradigma estrutural passo a passo e possuem imutabilidade, as declarações devem ser enxergadas como implicações matemáticas. Entre as características, estão as funções de alta ordem, ou seja, funções que recebem funções como parâmetros. Tipos polimórficos (um parâmetro cujo tipo não está restrito) e Avaliação preguiçosa (que permite cálculos sob demanda). Tipos comuns: Bool, sendo False e True funções construtoras de valor, Char, String, Int, Integer, Float, Double e Listas. As listas podem ser de qualquer tipo, o comando :t Lista retorna seu tipo. As funções são mapas de argumentos, com entradas de um tipo e saída de outro, mas não necessariamente.
112 JEAN DA SILVA NEVES
59 JHONATA SANTANA LOUZADA DE AGUIAR
60 JULIO NOVAES DA FONSECA Resumo Semana 2 - Julio Novais - RA 21073215 -------------------------------------------- Durante a Semana 2 aprendemos sobre: - Cálculo lambda: a história por trás, como funciona sua sintaxe, como escrevemos e açucares sintáticos - Combinador Y: o que é, como escrevemos e como utilizamos em Haskell - Conceitos básicos de haskell: tipos, funções, assinaturas, etc
61 KAREN OLIVEIRA DOS SANTOS Computabilidade é Área da Ciência da Computação que estuda a possibilidade de resolver um problema seguindo algorítmo Ambos artigos de Alan Turing e Alonzo trataram de um problema não computável Alan Turing descreveu a máquina de Estado Finita (Máquina de Turing) nesse paper Alonzo Church segue o raciocínio diferente de Alan, ou seja, usa computação como abstrações de funções que ele chama de funções de lambda. Naquela época não tinha confirmado o que erá computável ou não Alan Turing descreveu uma máquina universal na qual tudo era computável, mas não foi feito nenhum esforço para confirmar isso e os argumentos dele para confirmar esse pensamento eram usar a intuição, equivalência de duas definições e dar exemplo do que pode ser computável. Após o paper do Church, Turing adicionou o que o Church definifiu como efetivamente calculável é equivalente o que ele define como computável na sua máquina. Os problemas associados com Computabilidade são: Decisão, Função, Busca e Otimização. Linguagens de programações tem várias coisas (ponteiros, classes, laços e etc), porém Cálculo Lambda descreve problemas usando somente funções. Progrmação funcional surgiu do código lambda Sintaxe do lambda é composto por variáveis, definições de funções e aplicações de funções. Syntatic Sugar é diminuir a quantidade de informações Redução beta é uma forma de substituir ocorrência livres por uma outra variáveis. Forma normal é quando não pode ser redutível Combinator Omega não está na forma normal mas é irredutível.
62 KELVIN ALVES DOS SANTOS
63 KLEVERSON NASCIMENTO PINTO Coisas importantes sobre a linguagem: - Função são definidas nessa ordem: nome, parâmetros separados por espaço. - Por convenção é usado underscore - Lista é o nome do item seguido de 's', por exemplo item x faz parte da lista xs - Indentação é importante! - Usar espaços ao invés de tab - Tipos básicos: - Bool - Char - String - Int - Integer (a diferença pro Int é o tamanho, no Integer a memória é o limite. Integer é mais lento) - Float - Double - Listas: - Coleção de valores de mesmo tipo (pode ser vazia também) - Graças a avaliação preguiçosa do haskell podemos ter listas infinitas
65 LARISSA COPEL ROTHMAN Cálculo Lambda Computabilidade: estudo da possibilidade de resolver um problema seguindo um algoritmo. O cálculo lambda descreve a computação utilizando apenas funções. Sintaxe -> como escrever Semântica -> o que significa Forma normal: termos que não contém nenhum redex (expressão redutível). Non-Terminating Evluation: programas que não possuem uma forma normal, isto é, a sua redução leva a ele próprio. A linguagem funcional, em relação às linguagens reais, possui apenas funções. Dentro das funcionalidades esperadas, tem-se: -Booleanos -Registros -Números -Funções -Recursão As funcionalidades não existentes na linguaguem funcional são implementadas através das funcionalidades existentes, no caso, funções. IMPLEMENTAÇÃO DE BOOLEANOS Verdadeiro = \x y -> x Falso = \x y -> y IF = \b x y -> b x y IMPLEMENTAÇÃO DE REGITRSOS PAIR = \x y -> ??? -- Cria um par com elementos x e y FST = \p -> ??? -- Devolve o primeiro elemento SND = \p -> ??? -- Devolve o segundo elemento IMPLEMENTAÇÃO DE NÚMEROS ZERO = \f x -> x UM = \f x -> f x DOIS = \f x -> f (f x) TRES = \f x -> f (f (f x)) ... IMPLEMENTAÇÃO DE RECURSÃO fat = \f -> \x -> if x == 0 then 1 else x * f (x - 1)
109 LARISSA RODRIGUES DE ALMEIDA A programação funcional utiliza o cálculo lambda, que é um sistema formal para expressar computação baseado em abstração de funções e aplicação. A sintaxe desse sistema é composta por três elementos: variáveis, definição de funções e aplicação de funções. Com esses elementos, o cálculo lambda consegue implementar todos os outros tipos de lógicas de programação (booleanos, registros, números, funções e recursão). Além dessa característica da programação funcional, também temos que ela é declarativa, por esse motivo, temos código extremamente menores em relação aos outros paradigmas. A linguagem que será utilizada nesse curso é o Haskell. Essa semana tivemos duas aulas que demonstram os conceitos básicos dessa linguagem na prática. O Haskell é uma linguagem predominantemente funcional, possui como características: códigos concisos e declarativos, imutabilidade, funções recursivas, funções de alta ordem, tipos polimórficos e avaliação preguiçosa. Todas essas características são demonstradas na aula através da implementação em código para entendermos a realização de tudo isso na prática.
66 LEANDRO RIBEIRO DE ALMEIDA
67 LEANDRO VICTOR FERREIRA Haskell é uma linguagem com bastante utilidade na europa, decorrente das suas características. Códigos concisos e declarativos: Códigos conciso, pois expressa-se o as funções de maneira mais curta e objetiva, além de, essas funções informado querem que seja feito, ao invés de descrever passo a passo, sendo esta, sua característica declarativa. Imutabilidade: variáveis declaradas não podem ter seu valor alterado, isso facilita, pois não precisa instanciar, como ocorre em POO. Funções Recursivas: uma programação funcional, utiliza da recurso para realizar os “loopings” vistos em outros paradigmas, pois usa-se do imperativo e não da descrição do passo-passo além de violar a imutabilidade, por a variável i de um for, tem seu valor alterado no decorrer da execução. Função de alta ordem: Funciona com as funções composta da matemática, onde a variável de uma função recebe uma outra variável. Tipos polimórficos: São funções que não precisam ter os tipos de variáveis definidas, pois funciona para todas as classes de tipos. Avaliação preguiçosa: Quando um valor só será calculado se for solicitado, antes disso só há uma "promessa" de valor. Foi visto em aula o famoso “Hello Word!”, assim como as convenções utilizadas na programação em haskell, assim como a importância da indentação e layout, pois diferente de java e C, por exemplo, não há separação de blocos por meio de chaves. Foi visto os principais tipos e a maneira de declará-los, e também que :t diz qual o tipo da variável.Além de ver como utlizar Listas e Tuplas. Em funções vimos que elas agem como na matemática, declarando o tipo do domínio e imagem.
68 LEONARDO SANTIAGO HAMPSHIRE -- f a b -- Definição de função f(a, b) -- f a b + c*d --f(a, b) + c*d --> Em haskell não é necessário parenteses, porém -- podem ser usados no caso de delimitação de prioridades de execução ou melhor expecificação -- da sentença -- -- Unicode podem ser usados, porém pode dificultar a digitação. -- Nomes de funções, argumentos e variáveis iniciam com letra minuscula por convenção -- Para diferenciar as palavras em uma variável é utilido letra maíuscula -- Não se pode usar nomes pré utilizados pela linguagem para definir novas variáveis -- -- As listas de tamanho n são nomeadas com ns, -- As listas de variáveis x tornão-se xs e listas de caracteres tem o nome css -- -- ***Haskell considera a identaçao como delimitador de código*** -- Comentários -> usa-se --Comentário ou {- Comentários em Múltiplas Linhas -} -- -- Tipos de dados básicos (Conjunto de valores relacionados entre si) -- Int (-2^{63} ~ 2^{63}}), -- Integer -> Não possui limite (o limite seria a própria memória) -- Float (precisão de 7 dígitos), -- Double(Precisão de 16 Dígitos), -- Integer -- Bool (Usados com &&(e), ||(ou) e not(negaçao)), -- Char (Delimitado por aspas simples), -- String (delimitados por dupla aspas) -- -- Definição do tipo -> v :: T / onde v é a variável e T o tipo a ser definido -- ex: variavel :: Int -- -- o GHC já vem com suporte nativo para diversos tipos ** -> :t v -> Entrega o tipo da variável v -> Sobre Listas -> Tuplas, são sequencias finitas de componentes. -> Resume-se em duas listas de mesmo tamanho que comporta os valores e os tipos respectivos aos valores. -> O tipo de uma lista que contém uma tupla nada mais é do que o vetor que contém os tipos da tupla. -> Tuplas são escritas como (elemento1, elemento2, ...) -> Funções -> not :: Bool -> Bool -> even :: Int -> Int -> soma :: Int -> Int -> Int (Recebe dois inteiros e devolve um Inteiro) -> mult :: Int Int Int -> Int (Recebe 3 Inteiros e devolve um Inteiro) OBS: O retorno é sempre o último elemento em questão NO Arquivo ***.cabal*** -> ghc-options: -Wall -O2 -> Opção no compilador para warn --> Gramatica -> 5.3 :: Fractional p => p Fractional p -> Feine o tipo que p pode receber --> EVITAR USAR ERRORS --> **LISTAS LIGADAS** data [] a = [] | a : [a] Operador (:) -> Cons 1 : 2 : 3 : [] == [1, 2, 3] 0 : [1, 2, 3] => [0, 1, 2, 3] "999" == ['9', '9', '9'] -> True [1..10] == [1, 2, 3, 4, 5, 6, 7, 8, 10] [1, 3.., 10] == [1, 3, 5, 7, 9] [1, 3, ..] Lista infinita de numeros ímpares ** FUNÇÕES PARA TRATAR LISTAS ** --> !! -> gangbang -> Ex: xs !! 0 -> Retorna o primeiro elemento da lista (custo é proporcional a posição) --> head (Cabeça) -> head xs -> Cabeça da lista (Primeiro Elemento) --> tail (Cauda) -> tail xs --> take -> take 10 xs -> Retorna os 10 primeiros elementos de xs --> drop -> drop 10 xs -> elimina os 10 primeiros elementos de xs --> lenght (Não funciona em listas infintas) -> Retorna o tamanho de uma lista --> sum -> sum xs -> devolve a soma de todos elementos de xs --> product -> product xs -> Devolve o produto de todos os elementos de xs
101 LOUIS PHILLIPE SARDA DUBOIS Semana 2 – Aula 1: Cálculo de lambda: Utilizado para descrever computação apenas com funções. Exemplos \x -> x – função identidade \x -> (\y -> y) – retorna a função identidade \f -> \f (\x -> x) – função que aplica seu argumento (que é uma função identidade) na função identidade \x -> (\y -> x) – função que recebe dois argumentos e retorna o primeiro \x -> (\y -> y) – função que recebe dois argumentos e retorna o segundo \x y -> y – função que recebe dois argumentos e retorna o segundo Redução beta: (\x -> e1) e2 => e1[x := e2] e1[x := e2] significa e1 com todas ocorrências libres de x substituídas por e2 Dizemos que (\x -> e1) e2, B-reduz para e1[x := e2] Exemplo (\x -> (\y -> y)) 3 => ??? (\x -> (\y -> y)) 3 => \y -> y Equivalência alfa : renomeia as variáveis das funções para evitar conflito \x -> x => \y -> y Função normal: um termo-lambda na forma (\x -> e1) e2 é chamado de expressão redutível ou redex. O termo está em sua forma normal se não contém nenhum redex. Booleanos com lambda Verdadeiro = \x y -> x Falso = \x y -> y IF = \b x y -> b x y Registros – Tuplas PAIR = \x y -> (\b -> IF b x y) FST = \p -> p Verdadeiro SND= \p -> p Falso Numeros de Church ZERO = \f x -> x UM = \f x -> f x DOIS = \f x -> f (f x) TRES = \f x -> f (f (f x)) Combinador Y em Haskell y = \f -> (\x -> f (x x)) (\x -> f (x x))
74 LUCAS AKIRA HASEGAVA Introdução ao conceito de computabilidade Introdução sobre lambda aplicação do lambda em haskell exemplo de syntatic sugar exemplo de escopo de uma variavel exemplo expressão fechada reduções combinador omega booleans pair, fst, snd inc add assinaturas das funções exemplos de Where exemplos if then exemplos guards exemplos de Pattern Matching exemplos de como se utilizar listas e suas funções (!!, head, tail, etc) maior aprofundamento das listas utilizando compreensão de lista exemplos de recursão
73 LUCAS BRANDAO PEREIRA Lucas Brandão Pereira - 11201720262 RESUMO Cálculo λ Computabilidade - Área de estudo da ciência da computação que estuda a possibilidade de resolver um problema usando um algoritmo Dois matemáticos pioneiros da área Alan Turing Máquina de Turing - Máquina de estado finita que perimite ler, escrever e andar por fita de entrada, que por sua vez é uma fita de execução de tamanho arbitrário. Alonzo Church Cáculo λ - Sistema que formaliza expressões computacionais baseado em: Abstração de funções Aplicação usando APENAS atribuições de nomes e substituições Cáculo λ Descreve a computação utilizando apenas funções Composto por 3 elementos Variáveis Definição de funções Aplicação de funções Sintaxe do Cálculo λ Em sua sintaxe original a letra grega minúscula lambda (λ) é usada para definir funções. Por exemplo: Função identidade: λx.x Função que devolve a função identidade: λx.(λy.y) Sintaxe de Haskell Troca λ por \ . por -> Introdução ao Haskell Origem do Haskell Surgiu em 1990 com o objetivo de ser a primeira linguagem puramente funcional. Por muito tempo considerada uma linguagem acadêmica. Atualmente é utilizada em diversas empresas (totalmente ou em parte de projetos). Código O código em Haskell é compacto e declarativo Se declara o que se quer ao invés de ao inves de escrever um passo-a-passo (como nas linguagens imperativas) Imutabilidade Não existe o conceito de variável, pois os valores não variam uma vez que foram declarados Recursão Com a imutabilidade, não faz sentido existirem laços, logo se usa a recurão para se executar laços Funções de alta ordem São funções que podem receber outras funçoes como parâmetro Tipos polimórficos Não é necessário "tipar" os argumentos e retornos de uma função Avaliação preguiçosa Numa função, só se computa aquilo que for requisitado, permitindo estrutura de dados infinitas (listas infinitas etc) Funções Em Haskell, a aplicação de função é definida como: O nome da função Os parâmetros separados por espaço A aplicação de funções tem a maior precedência Tipos de dados Em Haskell os tipos sempre são usados com a primeira letra maiúscula Int - inteiros Bool - valores lógicos (true or false) Notação v :: T 10 :: Int True :: Bool Listas Listas são sequências de elementos do mesmo tipo ex: [1,2,3,4] :: [Int] [False, True, True] :: [Bool] ['o', 'l', 'a'] :: [Char] Tuplas Tuplas são sequências finitas de componentes, contendo zero ou mais tipos diferentes: (True, False) :: (Bool, Bool) (1.0, "Sim", False) :: (Double, String, Bool) Funções Sintaxe not :: Bool -> Bool even :: Int -> Bool Para escrever uma função com múltiplos argumentos, basta separar os argumentos pela ->, sendo o último o tipo de retorno: soma :: Int -> Int -> Int soma x y = x + y Polimorfismo Considere a função length que retorna o tamanho de uma lista. Ela deve funcionar para qualquer uma dessas listas: [1,2,3,4] :: [Int] [False, True, True] :: [Bool] ['o', 'l', 'a'] :: [Char] Em Haskell, a é conhecida como variável de tipo e ela indica que a função deve funcionar para listas de qualquer tipo. Overloaded types Considere agora a função (+), diferente de length ela pode ter um comportamento diferente para tipos diferentes. Internamente somar dois Int pode ser diferente de somar dois Integer (e definitivamente é diferente de somar dois Float). Ainda assim, essa função deve ser aplicada a tipos numéricos. A ideia de que uma função pode ser aplicada a apenas uma classe de tipos é explicitada pela Restrição de classe ( class constraint ). Uma restrição é escrita na forma C a, onde C é o nome da classe e a uma variável de tipo.
76 LUCAS DAVID VADILHO # Semana 2 ## Cálculo Lambda - Lambda & Computabilidade: tudo que é calculável por cálculo lambda é efetivamente computável - Funções: o mínimo que precisamos ter para chegar em algo turing completo ### Sintaxe Composta por variáveis, definições de funções e aplicação de funções. Se **e** não tem variáveis livres, **e** é expressão fechada ou _combinator_. Se não contém redex está na forma normal. A avaliação ocorre atavés de alfa e beta reduções até chegar na forma normal. ### Programando Como modelamos coisas só com funções - Booleanos - Verdadeiro = \x y -> x - Falso = \x y -> y - IF = \b x y -> b x y - NOT = \b -> IF b Falso Verdadeiro => \b -> b Falso Verdadeiro - AND = \b1 b2 -> IF b1 b2 Falso => \b1 b2 -> b1 b2 Falso - OR = \b1 b2 -> IF b1 Verdadeiro b2 => \b1 b2 -> b1 Verdadeiro b2 - Tuplas - Pares: IF - n-uplas: par de par ... de pares - Números - Definição: número de Church - chamada de uma função n vezes (~ succ(x)) - Operações - Recursão - Combinador Y: expressão lambda que devolve um ponto fixo para qualquer função lambda ## Conceitos básicos - Imutabilidade: não temos atribuição - Laços são implementados com recursões - Funções recebem funções como parâmetros - Tipos polimórficos - Lazy - Funções tem maior precedência - Identação] - Funções são mapas de argumentos (f :: T1 -> T2 -> ... -> Tn) - Guard expressions: `|` e `otherwise` - Recursão - Cálculo por substituição -> pode não ser constante em espaço - Pattern matching: `_` (_don't care_) - Cons `:` - Indexar em lista `!!` (são lista ligadas, não ocorre em tempo constante) - Compreensão de lista ### No `ghci` - `:t` ver tipo - `:r` recarrega modulos ### Warnings & otimização No `projectName.cabal`: ``` executable projectName ghc-options: -Wall -O2 ```
113 LUCAS DE SOUZA
44 LUCAS MAZIM DE SOUSA Na primeira parte das aulas desta semana estudamos o conceito de cálculo lambda, um sistema formal para expressar computação baseado em abstração de funções e aplicação usando apenas atribuições de nomes e substituições. Ela foi criada em 1930 por Alonzo Church e inspirou a criação de linguagens de programação baseadas no paradigma funcional, como o haskell. O calculo lambda é composto por apenas três elementos: (1) variáveis, (2) definição de funções (ou abstrações, ou função anônima) e (3) aplicação de funções. Uma expressão é composta pela variável e seu escopo. Dentre os casos especiais de expressão, estão os combinadores, o combinador Omega e o combinador Y. Em seguida estudamos sobre o haskell, uma linguagem criada em 1990 com o intuito de ser a primeira linguagem puramente funcional. Entre as principais características estão: (1) código conciso e declarativo, (2) imutabilidade, (3) funções recursivas, (4) funções de alta ordem, (5) tipos polimórficos e (6) a avaliação preguiçosa. Vimos as convenções design de programação da linguagem, os tipos de dados básicos, as estruturas de listas, tuplas, funções e diversos comandos padrões do haskell que serão muito utilizados no decorrer da matéria.s
72 LUCAS SILVA AMORIM
77 LUCAS YUDI FUKAZAWA CASSIN Cálculo lambda Church e Turing estavam procurando por uma definição do que é computável ou não. Chegaram a mesma conclusão com estudos distintos, é computável se é computável utilizando a máquina de Turing ou o Cálculo Lambda Cálculo lambda mostra que o mínimo necessário para uma linguagem são as funções Cálculo Lambda 3 elementos Variáveis Definições de funções Aplicações de funções Semântica Passo alfa Renomeia um parâmetro formal Redução beta Chama uma função O termo está na forma normal se não contém mais nenhum redex A partir das funções pode-se ter: booleanos, registros, números e recursão (Combinador Y) Combinador Y Devolve um ponto fixo para qualquer função passada Por esse aspecto é utilizado como parâmetro em uma função recursiva, uma vez que a função aplicada ao ponto fixo devolve ele mesmo Haskell Puramente funcional Códigos concisos e declarativos Não existem variáveis, as coisas são imutáveis Não existem laços, pois não existem variáveis, logo utiliza-se funções recursivas Tipo polimórficos: permite definir funções genéricas Aplicações de funções tem maior precedência Linguagem fortemente tipada, alguns deles: Bool, Char Listas só podem ter um tipo Tuplas podem ter mais de um tipo As funções precisam de assinaturas Funções podem ter uma cláusula "where" que contém sub-cálculos dentro da função "Guards" reduzem o número de "ifs" e deixam o código mais fácil de ler. (Switch-case). Otherwise = default "Pattern matching" são funções aninhadas que caso os parâmetros encaixem em uma das declarações, essa é computada. Considera a sequência que aparece. Ex.: mult 0 _ = 0 mult _ 0 = 0 mult 1 y = y mult x 1 = x mult x y = x * y Listas são formadas por [o que estará na lista | vindo desse conjunto, com essa restrição]. Ex.: [x | x <- [1..1000], x `mod` 3 == 0]
64 LUCAS ZOCCHIO Se existe um problema e um algoritmo que resolve aquele problema, então o problema é computável. A. Church e A. Turing escreveram artigos que tratavam de problemas computáveis. Church usou o conceito de cálculo-λ como um cálculo universal. O cálculo-λ descreve computação em termos de funções. A sintaxe do cálculo-λ envolve variáveis, que nomeiam um valor na durante o cálculo, definição de uma função anônima (função-λ) e aplicação de funções. As variáveis presentes num cálculo-λ podem ser ligadas ou não e o cálculo-λ é dito na forma normal se não possui expressões redutíveis por passos α ou β. O combinador-Ω não pode ser reduzido a uma forma normal. É possível definir booleanos, registros, números e recursões usando funções (cálculo-λ). Para a representação de números, utiliza-se a representação de Church, onde diferentes números são representados pelo número de vezes que uma função é aplicada. O combinador-Y, tal como o Ω, não pode ser reduzido a uma forma normal. Além disso, é um ponto fixo de qualquer função. Por conta dessa propriedade pode ser usado para implementar a recursão, por exemplo, para o cálculo de fatorial. O código em Haskell é conciso e declarativo, os valores de variáveis são imutáveis (são mais como nomes), laços são implementados através de recursão (pois laços for e while envolvem o uso de variáveis), permite tipos polimórficos (funções que aceitam parâmetros de diferentes tipos) e utiliza avaliação preguiçosa. Nomes de funções, argumentos e variáveis começam com letra minúscula, blocos lógicos são definidos pela identação. Tipos são soleções de valores relacionados entre si. A avaliação e tipos do Haskell pode adiar a determinação do tipo. Elementos em listas devem ter um mesmo tipo, mas em tuplas podem ter tipos diferentes. Funções podem ter os tipos definidos separando-os por uma seta.
78 LUCCA IANAGUIVARA KISANUCKI Dentro do Haskell podemos utilizar BASTANTE função lambda, os tipos de dados são definidos por: Int, Float, Double, Char, String, Bool... É possível fazer manipulação de listas usando as seguintes funções básicas: head, tail, take, drop, length, !!, Podemos instanciar listas de diferentes formas e com padrões, [], [1,2], [1,2..], [1..100], [3, 6, 9, 999] E usando lambda [x | x <-[1,2..100], x `mod` 2 == 0] Além das condicionais IF e ELSE, também temos o Guard Expressions usando | (pipe)
79 LUIZ FELIPE LEAL GOMES AZZOLINI
81 MARCELO CECILIO FAGUNDES DA SILVA FILHO Durante essa semana, demos uma olhada no conceito de calculo lambda as bases da linguagem Haskell. O calculo lambda foi criado por Alonzo Church, para resolver o problema de descobrir se determinado problema pode ou não ser resolvido através de um computador. Nele as funções são abstraídas em atribuições de nomes e substituições. O calculo lambda então resume toda a programação (numeros, condicionais, laços, operadores matematicos e etc) apenas em funções. A linguagem Haskell usa o conceito de calculo lambda em sua. A letra λ é usada para representar o calculo lambda, já em haskell é usado o operador \. O cálculo lambda é dividido em 3 partes: Variavél: o nome que assumirá um valor durante a computação Abstração: é o formato da função. Aplicação: é a substituição das variáveis pelos valores esperados. Por exemplo: (\x -> x) 2 => 2. Aqui o valor x foi substituído por 2, resultando em 2. A linguagem Haskell é uma linguagem funcional. Ela é estritamente tipada, o que significa que ela não permite operações entre tipos diferentes. O compilador tentara determinar o tipo da operação, porém usará tipos genéricos como Num (ao invés de Int, Float e etc) e Fractional (ao invés de Float, Double e etc). Por isso o ideal é sempre determinar o tipo de entrada e saída de uma função. As listas são algo muito útil em Haskell. São semelhantes aos arrays em outras linguagens permitindo o agrupamento de vários itens de mesmo tipo. Como haskell apresenta avaliação preguiçosa o uso de listas infinitas não é impossível, desde que apenas uma parte finita da lista seja usada. Além disso é possível ser feito compressão de listas e assim ter uma lista apenas com valores que obedeçam a uma determinada regra. Em Haskell não há laços de repetição, portanto todas as repetições são expressas recursivamente.
82 MARCELO MARTINS OLIVEIRA
95 MARIANA MIWA OKUMA MIYASHIRO Cálculo lambda: - Church-Turing: papers sobre computabilidade (criar algoritmo para problema) - Turing: Máquina de estados finita - Church: cálculo lambda - essencialmente, só precisamos de funções para programar - cálculo lambda: variáveis, definição e aplicação de funções - Haskell: \ substitui lambda e -> substitui . do cálculo lambda - expressões fechadas (corpo sem variáveis livres) - semântica alfa(renomear) ou beta(aplica expressão usando variável livre) - redex: expressão redutível, pronta para ser aplicada - forma normal: sem redex - um termo e é avaliado até chegar na forma normal - combinador omega (avaliação que não termina) - como fazer outras funcionalidades com cálculo lambda? Há adaptações para representar booleanos, registros, números e recursão (também usada para modelar laços e utiliza combinador Y) Haskell básico I: - código conciso e declarativo, imutabilidade de variáveis, laços implementados a partir de recursão - utiliza funções de alta ordem, tipos polimórficos e avaliação preguiçosa - comparável com notação matemática - requisitos nomes (função começa com minúscula, tentar não usar unicode, etc) - espaço vs tabs -> espaços Haskell básico II: - a: variável de tipo que indica que a função deve funcionar com qualquer tipo - pode ser feita restrição de classe - cláusula where: define nomes intermediários - condicional (if-then-else) - expressões guardadas: podem substituir condicionais, que possui ‘otherwise’ definido como True - expressões lambda: definem função sem nome para uso geral - operador: pode ser criado na forma de função ou usado entre `` - listas: muito úteis em Haskell - todos os valores do mesmo tipo - definição recursiva ou com syntax sugars - pode ser infinita, por causa da avaliação preguiçosa - recuperar elementos com !!, head, tail, drop - tamanho: length - soma e produtória: sum e product - concatenar: ++ - string: lista de Char - sintaxe parecida com a matemática para geradores - and: retorna True se todos os elementos da lista Bool são True - recursão: compor 1 ou mais casos base e depois a chamada recursiva - facilita trabalhar com listas
85 MATHEUS ALEXANDRE DE SENA
83 MATHEUS DA COSTA BAIO Cálculo Lambda (λ) Computabilidade -> Possibilidade de resolver um problema com algoritmo. Turing -> Computar -> Máquina Universal / Church -> Calcular -> Cálculo Lambda > Dois conceitos diferentes que provam a mesma coisa -> Tudo que é calculável é computável e vice-versa. Problemas: Decisão/Função/Busca/Otimização Cálculo lambda descreve computação apenas utilizando funções. Composto por três elementos: Variáveis, definição de funções, aplicação de funções. Letra lambda(λ) é utilizada para definir as funções. Semantica. Podemos reescrever as expressões utilizando duas regras: Passo ALFA -> Renomeia um parâmetro formal Passo BETA -> Aplica uma expressão utilizando uma variável livre (i.e. chama uma função) Um termo λ na forma (\x -> e1) e2 é chamado de expressão redutível ou REDEX. O termo está na sua FORMA NORMAL se não contém nenhum redex. AVALIAÇÃO acontece em uma expressão até ela chegar em sua forma normal Combinador ômega -> Impossível chegar na forma normal (looping de avaliação) O combinador Y Permite expressar as relações de recursão Objetivo de Haskell -> ser a primeira linguagem puramente funcional. Por muito tempo considerada uma linguagem acadêmica. Atualmente é utilizada em diversas empresas. Haskell -> 1) Códigos concisos e declarativos 2) Imutabilidade -> Não existe conceito de variável, apenas nomes e declarações. 3) Funções Recursivas -> Não existem laços devido a 2) 4) Funções de alta ordem -> funções podem receber funções como parâmetros 5) Tipos Polimórficos -> 6) Avaliação Preguiçosa -> o resultado só é computado quando requisitado. Convenções: Nomes de funções começam com minúsculo Listas são nomeadas acrescentando “s” ao nome do que ela representa Layout semelhante ao Python. Identação importante. Usar espaço pois é definido igualmente em qual seja o editor. Comentário iniciam com “--” ou “{- -}”
84 MATHEUS DE ALBUQUERQUE ACCIOLY RODRIGUES
86 MAYZA CRISTINA DA SILVA Computabilidade é uma área de estudo central da Ciência da Computação. (Resolver um problema seguindo um algoritmo) - Máquina de Turing, 1936 (Máquina de Estado Finita) Cálculo λ: abstração de funções e aplicação usando apenas atribuições de nomes e substituições . Alonzo Church, 1932-1940 (versão tipada) Problemas associados: Decisão, função, busca e otimização Uma linguagem deve ser descrita em função de sua sintaxe e semântica Sintaxe do Cálculo λ: - Variáveis - Definição de funções - Aplicação de funções (λ) é usada para definir funções. Semântica: Passo α: renomeia um parâmetro formal. Passo β: aplica uma expressão utilizando uma variável livre (ou, de maneira mais simples, chama uma função). Redução β Computação por substituição e busca - Se você vir uma abstração aplicada a um argumento, pegue o corpo da abstração e substitua todas as ocorrências livres do parâmetro formal pelo argumento Programando com λ Booleanos: Decisões no formato: if b then e1 else e2. Registros: Um par de x e y é apenas algo que permite você escolher entre x e y! Ou seja, uma função que recebe um booleano e devolve ou x ou y Números Naturais O combinador Y Recursão Em Haskell, poderíamos escrevê-la da seguinte maneira: fat x = if x == 0 then 1 else x * fat (x - 1) -- Ou usando lambda fat = \x -> if x == 0 then 1 else x * fat (x - 1) Contudo, em cálculo λ isso não é possível! Funções são anônimas! fat faz referência a si própria por nome! O combinador Y O combinador Y nos permite escrever uma expressão λ cuja avaliação se repete indefinidamente, tal qual o combinador Ω, mas que diferentemente deste faz algo útil durante cada redução: a avaliação da função f Haskell não aceita tipos infinitos pois isso poderia causar problemas (laços infinitos) no verificador de tipos do compilador
18 MIGUEL DOS REIS
88 MIGUEL MIRA FONSECA Haskell é uma linguagem de tipagem forte, cada variável tem um tipo, que são conjuntos de valores que se relacionam entre si, como Int e Bool, que começa com letras maiúsculas. Temos listas que são sequências de elementos de um mesmo tipo, como [1, 2, 3] e [‘a’, ‘b’, ‘c’]. Podemos declarar uma lista do tipo inteiro como [Int] e uma lista de listas de inteiros como [[Int]]. Já uma tupla são sequência de elementos que podem ser de tipos diferentes, como (True, False). Funções em Haskell são mapeamento de um tipo para outro tipo, e são escritos da forma T1 -> T2, fazendo o mapeamento do tipo T1 para T2. A assinatura de uma função aceita o que é chamado de class constraint, que seria uma restrição de como uma variável deve se comportar. Uma restrição da forma Num a => a -> a significa que a função recebe um valor do tipo a e retorna um valor do tipo a. Para facilitar a organização do corpo da função podemos usar a clausula Where para armazenar resultados de operações intermediárias. Condicionais podem ser feitos através do construto if ... then ... else, através de guards ou pattern matching. Esse último permite simplificar expressões onde a expressão utilizada no guard trata-se de uma igualdade. Temos também compressão de listas, da forma [x + 1 | x <- [1..10], x > 4], que especifica que dado uma lista de 10 números, deve ser selecionado os elementos maiores que 4, e para cada elemento selecionado vamos somar um, e retornar a lista desses elementos todos. Por fim não existem construtos de loop na linguagem, o qual devem ser substituídos pelo uso de recursão.
89 MURILO GUIMARÃES BALLE Essa semana foi abordado conceitos de Haskell básico. Foram abordados os conceitos de tipos e classes padrões, que são basicamente os mesmos tipos encontrados em linguagens de outros paradigmas já abordados durante o curso de BCC, com adição das tuplas (foi a primeira vez que abordaram esse tipo na UFABC durante minha trajetória). Também foi abordado o assunto de declarações de funções e arguementos e como realizar essa tarefa em Haskell, bem como a importância das assinaturas de função. Falando sobre o tipo Lista, foi ensinado as principais funções com listas, como geradores de listas, as funções sum, null, d, tail, take, drop, etc. Foi abordado também o tópico de compreensão de listas, o qual se parece muito com alguns exercícios sobre conjuntos que foram dados em Bases Matemáticas. Por ultimo, foi dado conteúdo sobre recursão e recursão em listas, onde foi amarrado o nó sobre todo o conteúdo dado anteriormente.
92 NATALIA LEITE VARES DE SOUZA Cálculo λ, inventado por Alonzo Church na década de 1930, pode ser definido como “a menor linguagem de programação do mundo”. A sintaxe do Cálculo λ é composta por 3 elementos: variáveis, definição de funções e aplicação de funções. Com o Cálculo λ e o Combinador Y é possível definir diversas funcionalidades, como: booleanos, registros (tuplas, structs, ...), números, funções e recursão. A programação em Haskell tem como características: - Códigos concisos e declarativos: o programador declara o que ele quer ao invés de escrever um passo-a-passo. - Imutabilidade: não existe um conceito de variável - Funções recursivas - Funções de alta ordem: funções podem receber funções como parâmetros - Tipos polimórficos - Avaliação preguiçosa No Haskell temos algumas convenções como: - a obrigatoriedade de iniciar nomes de funções com letras minúsculas, - as listas são nomeadas acrescentando o caractere 's' ao nome do que ela representa, - os blocos lógicos são definidos por indentação tornando a preocupação com layout algo relevante, para auxiliar na indentação é importante utilizar espaço ao invés de tabs. Os tipos de dados disponíveis no Haskell são: tipos básicos (Bool, Int, Float, String, ...), listas, tuplas e funções. Um conceito importante do Haskell são as assinaturas de funções, responsáveis por definir o tipo de entrada e tipo de saída resultante da função. Dentro de uma função, para definir nomes intermediários podemos usar a cláusula where. Além disso também é possível utilizar condicionantes, como if-then-else. Para a estrutura de listas o Haskell conta com um conjunto de funções básicas para manipulação de listas já pré-estabelecido. Para as listas implementadas em Haskell é possível utilizar os conceitos matemáticos quando falamos de conjuntos, por exemplo, {x2∣x∈{1..5}} pode ser definido como [x^2 | x <- [1..5]], o que facilita quando queremos criar uma lista com regras específicas
91 NATALIA REGINA COSTANZI Semana 2 - Cálculo λ Computabilidade: estuda a possibilidade de resolver um problema seguindo um algoritmo. Máquina de Turing: modelo criado por Alan Turing em 1936. Consiste em uma Máquina de Estado Finita cuja entrada é provida por uma fita de execução de tamanho arbitrário. A máquina permite ler, escrever e andar por essa fita. Cálculo λ: Criado por Alonzo Church na década de 1930, é um sistema formal para expressar computação baseado em abstração de funções e aplicação usando apenas atribuições de nomes e substituições. Uma linguagem do cálculo λ deve ser descrita em função de sua sintaxe e semântica. Problemas associados: -Decisão: Exemplo: Verifica se um número é primo -Função: Exemplo: inverter string -Busca: Exemplo: buscar um clique em um grafo -Otimização: Exemplo: maximização de lucros em investimentos Sintaxe do cálculo λ é composto de 3 elementos: -Variáveis -Definição de funções -Aplicação de funções Um programa é definido por uma expressão ou termos λ que podem assumir 3 formas -Variável -Abstração ou função anônima -Aplicação ou chamada de função Açúcar sintático: Não aumenta o poder de expressividade da linguagem, mas deixa o programa mais prático. Escopo de uma variável: Indica a visibilidade de uma variável (variáveis podem estar ligadas ou livres). Expressões fechadas ou combinadores: não tem variáveis livres. Semântica: Regras: -Passo α: renomeia um parâmetro formal -Passo β: aplica uma expressão utilizando uma variável livre. Redução β: redução de uma expressão por meio do passo beta. Equivalência α: Renomeia as variáveis de uma função para evitar conflito Redex: termo λ na forma (\x -> e1) e2 Forma normal: Termo que não possui redex. Avaliação: Sequência de passos que leva termo λ à sua forma normal. Non-terminatng evaluation: Ocorre quando não é possível atingir a forma normal. Temos então o combinador Ω.
90 NATHALIA CORREA DOS SANTOS Nessa semana estudamos a teoria de cálculo lambda, sua sintaxe e algumas aplicações, além de termos visto uma introdução a Haskell, uma linguagem que utiliza o paradigma funcional. O cálculo Lamba é um sistema formal em que as expressões computacionais são funções abstratas que utilizam apenas de atribuições de nomes e substituições, sendo composta apenas por 3 elementos: variáveis, definições de funções e aplicação de funções. Iniciando nossos estudos em haskell, nessa semana vimos como definir funções, tipos básicos de dados, a utilizar listas e condicionais, além de funções anônimas e operadores. Um ponto bastante importante da linguagem Haskell é a definição das assinaturas das funções, pois todo o desenvolvimento do código partirá dessa definição, é na assinatura que definimos os tipos de variáveis que nossas funções irão receber e retornar como resposta. Por se tratar de uma linguagem funcional também é de extrema importância a utilização de recursão nesse paradigma.
100 PAULO GABRIEL MASSA
96 PAULO HENRIQUE EIJI HAYASHIDA Computabilidade como concluido por Turing e Church, tudo que é calculavel com cálculo lambda é computavel numa máquina de Turing. Problemas de computabilidade envolvem decisão, função, busca, otimização. Sintaxe do cálculo lambda é composto por três elementos: variáveis, definição de funções e aplicações de funções. Se expressões tiverem apenas variáveis ligadas temos uma expressão fechada, ou um combinador. A variável de uma função está ligada quando essa aparece em seu corpo, caso contrário ela é dita livre. Expressões são reescritas através de passo alpha, renomeação de variáveis, ou passo beta, substituição das expressões nas funções. Uma expressão normal é uma expressão que não possui reduções beta a serem aplicadas. Açucar sintatico é a simplificação de expressões para uma representação mais compacta. Através das funções pode-se implementar booleanos, tuplas, números, registradores e recursões. Recursões utilizam uma variação do combinador omega, expressão que quando reduzida chega a expressão inicial, chamando combinador Y que aplica uma função recursivamente. Haskell possui algumas caracteristicas como: Códigos declarativos e concisos, declarações das funções a serem aplicadas; Imutabilidade, onde variável definidas com um valor, não podem ser alteradas; Funções recursivas, como variáveis não podem incrementar, laços são implementados por recursão; Funções de alta ordem, onde usa-se funções como parametros para outras funções; Tipos polimorficos, podem receber classes de tipos, não precisando ser um tipo especifico; Avaliação preguiçosa que fornece uma promessa de execussão, calculando o valor somente quando solicitado. Listas de elementos, por convenção utiliza-se um 's' após o nome da variável. Para definir tipos em haskell utiliza-se ::, tipos suportados são os que vemos na maioria das linguagens como Bool, Char, String, Int, Float, Double. Tuplas são sequências finitas que contém elementos de tipos diferentes. Funções recebem uma entrada de um tipo podendo retornar uma saída de tipo diferente.
99 PEDRO ANTUNES NEGRÃO Na segunda semana de aula foi apresentado o que é cálculo lambda, incluindo combinador Y, redução Beta, como se obtém diversas estruturas conhecidas de outras linguagens de programação através do cálculo lambda, por exemplo laços e tomadas de decisões, etc. Além disso foi apresentado os conceitos básicos da linguagem Haskell, começando pela definição de funções e indo até recursão de listas. Por definição, cálculo lambda é um sistema que utiliza apenas atribuições de nomes e substituições, ou seja, ele descreve computação utilizando apenas funções. E o mais incrível é que utilizando apenas funções é possível desenvolver todas as estruturas ou blocos lógicos que estamos acostumados nas outras linguagens de programação, como booleanos (True / False / Condicional => IF), registros (structs, tuplas, etc.), denifição de números e recursão (é através da recursão que é possível obter laços). Além disso, ao modificar o combinador ômega, que nada mais é do que uma avaliação que não tem fim (podemos fazer infinitas reduções Beta que sempre é obtido a expressão inicial, ou seja, nunca chegamos na forma normal), é possível obter o combinador Y, que é uma expressão lambda que sempre retorna um ponto fixo de uma função lambda. (ponto fixo é um elemento do domínio de uma função que sempre retorna ele mesmo, i.e. 0, 1 e -1 são pontos fixos de f(x) = x^3). Agora falando sobre os conceitos básicos de Haskell, ela é uma linguagem puramente funcional, declarativa, não existe váriaveis (imutabilidade), apresenta funções recursivas (criação de laços), funções de alta ordem (funções podem receber funções como parâmetro), avaliação preguiçosa (uma função será computada apenas quando for requisitada, evitando assim computações desnecessárias e possibilita estruturas de dados infitnitas) e apresenta tipos polimórficos (i.e. variável de tipo "p" e "a").
97 PEDRO BRAGA DOS SANTOS BACELLAR
98 PEDRO MACHADO NERY DOS SANTOS A linguagem do cálculo lambda se baseia numa sintaxe com definição e aplicação de funções, além de variáveis, ligadas ou livres – uma expressão com variáveis livres é chamada fechada ou combinador. Semanticamente, se baseia na renomeação de parâmetros formais (passo alfa) e aplicação de expressões com variáveis livres (passo beta). Este último ponto define a chamada computação por substituição (de um parâmetro por uma variável livre) e busca (das ocorrências de dado parâmetro no corpo da função em que ele é definido, para sua substituição). Termos lambda (expressões) beta-redutíveis aceitam substituições enquanto que termos em forma normal não (estão prontos para serem avaliados). Termos lambda são avaliados somente se existir uma sequência de passos que os levem à forma normal. O combinador ômega é uma expressão tal que é impossível se chegar a uma forma normal, isto é, uma função que gera a si mesma e pode ser utilizada para modelar sequências infinitas. Booleanos são modelados a partir de funções. Isto pode ser realizado principalmente convertendo a estrutura if-else no retorno de um primeiro ou segundo parâmetro (Verdadeiro ou Falso). Essas expressões são então utilizadas para a construção de operadores lógicos (não, e, ou) e registros (estruturas como pares e tuplas). A aritmética é construída através dos chamados números de Church, com um natural N sendo codificado com a chamada de uma função N vezes. Analogamente a outros paradigmas, a chamada de uma função 0 vezes é correspondente à função codificadora do booleano Falso. A construção de uma função incremento, que realiza a chamada de uma função adicionalmente ao número N já codificado, gerando N+1, pode ser utilizada para a construção de uma soma. O combinador Y é utilizado para a modelagem de recursão, suplantando a necessidade de laços não presentes em linguagens puramente funcionais. É baseado no combinador ômega.
106 PEDRO REGIO SHOJI
102 PIETRO DI CONSOLO GREGORIO Computabilidade é a área de estudo sobre os problemas que podem ser resolvidos seguindo um algotimo. O Cálculo λ foi criado na década de 1930 por Alonzo Church e se trata de um sistema formal capaz de descrever computação utilizando apenas funções, através de atribuições de nomes e substituições. Há apenas três elementos básicos no Cálculo λ: variáveis, definições de funções e aplicações de funções. Através de processos de aplicações e substituições de funções, reduções, equivalências e uso de combinadores, é possível construir todos os elementos necessários para se ter uma linguagem de programação. A linguagem Haskell foi criada em 1990 com o objetivo de se criar uma linguagem puramente funcional. Algumas das características do Haskell são: códigos concisos e declarativos, imutabilidade, funções recursivas, funções de alta ordem, tipos polimórficos e avaliação preguiçosa. Algumas das convenções da linguagem são: nomes de funções começam com letra minúscula, listas terminam com o caractere 's', presença de nomes reservados que não podem ser usados e blocos lógicos definidos pela indentação do código. Alguns dos tipos básicos são: Bool, Char, String, Int, Integer, Float e Double. As listas são sequências de elementos do mesmo tipo e seu tamanho não é especificado, já as tuplas podem possuir zero ou mais tipos diferentes e seu tamanho é especificado e portanto, finito. Ao definir uma função, deve-se inserir também sua assinatura, especificando os tipo dos parâmetros de entrada e de saída. É possível usar alguns artifícios como where, guards e pattern matching para que o código fique mais claro para o programador. As listas são frequentemente usadas na linguagem e existem diversos operadores que facilitam a sua manipulação. A recursão é usada para iterar sobre expressões e listas até que um caso base seja atingido, exercendo um papel similar aos laços das linguagens estruturadas.
103 PIETRO RISCHI NUNES As assinaturas de funções servem para indicar os tipos dos parâmetros de entrada e a saída da função. Na assinatura é possível identificar como a função se comporta, e quais são os tipos esperados, se algo não estiver de acordo, o compilador irá acusar, mostrando o erro e motivo, facilitando a depuração do código.
16 RAFAEL BRUNO FERREIRA FIGUEIREDO Introdução a Haskell: Puramente funcional, código declarativo, imutável, não há laços de repetição, somente recursão, avaliação preguiçosa: "só executa se precisar". Funções podem receber funções como parametro. Tipos Polimórficos. convenção: s no fim das variaveis significam listas! Tipos de dados: v :: T -> definição do tipo de alguma coisa, seja função ou variável. Int - inteiros Integer - Inteiro de tamanho arbitrário Float Double Bool - Booleano Char - caractere unicode! Strings - Limitado po aspas duplas "Ola Mundo" Note que o sistema de tipos do haskell deixa o mais pra frente possível pra deficnir o tipo que vai ser usado. Listas - Podem ser infinitas [] Tuplas - Finitas () Assinaturas: Quando usar na assinatura tipos que nao existem, como 'a' ou 'b', o tipo da variavel nao é limitada e se adapta. Where: possibilita escrever a função em ordem diferente. O where não tem ordem, o compilador resolve o bloco where inteiro "de uma vez". Expressões guardadas: Forma de encadear condições de forma de fácil escrita e entendimento. Pattern matching: Cria padroes nas entradas da função que facilitam o resultado da funçao, como tratar multiplicação e soma com 0. Usar _ diz para o compilador que nao importa a variável. Expressão Lambda/anônima: Nao precisa nomear a função, apenas declara entradas e saidas. Listas: Usa qualquer tipo do haskell, separados por virgula. String é um açucar sintático para criar lista de char. Toda lista em haskell é lista ligada entao é custoso pra andar pela lista. !! ->função para indexar a lista: xs !! 0 -> pega primeiro elemento. take -> pega os n numeros do inicio da lista drop -> retira os n numeros do inicio da lista lenght -> tamanho da lista sum -> soma dos elementos. product -> produto de todos os elementos expressões geradoras -> proximo da definição matematica de funções e pode ser possivel realizar laços em algumas aplicações.
104 RAFAEL PAUWELS DE MACEDO O cálculo lambda se baseia na abstração de funções e aplicação das mesmas usando apenas atribuições e substituições, isso tornou possível a redução de diversos problemas de linguagens a uma única solução, as funções. A sintaxe dessas funções se baseiam em três elementos, variáveis, definição de funções e aplicação de funções. Um dos conceitos interligados com o cálculo lambda é o uso de combinadores para reescrever e simplificar funções lambda. Falamos que uma função está em sua forma normal se não temos nenhum combinador que pode reduzir a função, esses combinadores são chamados de redex. As lambdas são capazes de representar inúmeras funcionalidades presentes em outras linguagens, como booleanos, registros, números, funções e recursões. Sendo esse último ponto, a recursão, resolvido com a utilização do combinador Y, que torna possível a escrita de funções recursivas com a introdução do conceito de ponto fixo na expressão. Assim conseguimos escrever expressões lambda que a cada redução causa a execução da função f. Dentro dos conceitos básicos da linguagem começamos vendo o sistema forte de tipos presente em Haskell e como fazemos o uso do polimorfismo para representar o tipo de cada argumento e do retorno de casa expressão. Vimos também o uso das funções de controle de fluxo com condicionais. O próximo ponto foi a instersecção do tópico anterior, com a avaliação de expressões lambda dentro do Haskell. A construção de listas se baseia na utilização de syntax sugars que nos permite facilmente criar listas [1, 2, 3], listas por faixas [1..3] e listas infinitas [1..]. As listas infitas explorar a caracteristica lazy da linguagem, ou seja, mesmo a lista sendo infinita nós só vamos construir que usarmos em tempo de execução.
105 RAPHAEL RAMOS DA SILVA
69 RENAN FERREIRA LIMA O estudo do cálculo lambda tem em vista o apresentado por Alan Turin e Alonzo Church, de forma sucinta pode ser descrito como: tudo que é efetivamente calculado em um cálculo lambda é computado em uma máquina universal. A sintaxe do cálculo lambda é dividida em três elementos: variáveis, Definição de funções, Aplicação de funções. A letra grega lambda é utilizada para definição desse tipo de função, no Haskell está é subtituída pelo caracter \ , de tal forma que pode-se definir a função identidade como: \x -> x, onde ‘-> ‘representa o caracter ‘.’. Quando se trabalha com cálculo lambda, utiliza-se a forma normal, i. e., emprega-se beta reduções em determinadas funções até obter-se uma forma reduzida onde a função possa ser avaliada conforme as convenções. Para operação com números é utilizado o conceito de números de Church, onde um número N é definido através da chamada de uma função N vezes. Analisando um conjuto de números naturais, esse tipo de representação remete a de Peano na álgebra. A partir disso, é possível implementar operações matemáticas como soma, produto, entre outras. É válido destacar que no cálculo lambda as funções não tem nome. Se tratando de recursividade é possível implementá-la usando o combinador Y, o qual é uma expressão lambda que devolve um ponto fixo para qualquer função lambda. No cálculo de um fatorial, por exemplo, pode-se aplicar o combinador Y, que é um ponto fixo da função fatorial. Com os conceitos abordados é possível implementar o cálculo lambda e o combinado Y utilizando o Haskell.
107 RENAN GONCALVES MIRANDA Tudo que é calculado em um cálculo lambda é computável em uma máquina universal, hoje o que é considerado calculável ou computável usando o calculo lambda ou a máquina de Turing. O cálculo lambda mostra que para descrever qualquer algoritmo é necessário somente de funções. A sintaxe do cálculo lambda tem 3 componentes, variáveis, definição de funções e aplicações de funções. O escopa de uma variável indica onde a variável é visual, em que lugar podemos usar aquela variável. Quando a variável está fora do escopa ela é chamada de variável livre, caso esteja é chamada de variável ligada. Redução beta é quando aplicamos uma expressão utilizando uma variável livre. Equivalência alfa é apenas a renomeação as variáveis, para evitar conflitos de nomes e para ficar mais fácil o entendimento do escopo. Uma redex é uma função que está pronta para ser aplicada. Um combinador ômega, é quando é aplicado uma beta redução e não conseguimos chegar na forma normal, pois sempre teremos uma função aplicável. Nas linguagens reais tem as seguintes funcionalidades que podem ser aplicadas a função lambda, booleanos, registros (structs, tuplas, ...), números, funções e recursões. O combinador Y é uma expressão lambda que devolve um ponto fixo (é um elemento do domínio de uma função que é mapeado para si mesmo pela função, exemplo 0 é ponto fixo da função f(x) = x³) para qualquer função lambda. o combinador Y é utilizado para a elaboração de funções recursivas utilizando cálculo lambda.
115 RENATO VINICIUS TURTIENSKI POSSA Calculo lambda Conceitos básicos de Haskell: As características de Haskell advém das teorias de Turing e Church sobre cálculo lambda, "que nada mais é do qua criação e aplicação de funções", tem por objetivo a resolução de problemas de Decisão, Função, Busca e Otimização O Haskell surgiu em 1990 tendo por objetivo ser a primeira linguagem puramente funcional, é bastante parecida com a linguagem matemática no que diz respeito a declaração de listas e funções. As características do Haskell são: - códigos consisos e declarativos: há a declaração do objetivo ao invés de "escrever para a máquina" uma receita de passos a serem seguidos. - Imutabilidade: não há conceitos de variáveis, ou seja não acontece a declaração de variáveis globais ou locais como em outras liguagens de programação, assim sendo, qualquer declaração será uma constante -Funções Recursivas: "Serve pra substituir os laços" Hihi - Funções de alta ordem: tem como parâmetro outra função, isso você encontra em outras linguagens - Tipos polimórficos: permite que uma função "sirva para vários tipos de dados", podendo servir para int, double, chars uma mesma função =D -Avaliação Preguiçosa: Guarda um pouquinho da RAM que será usada nas páginas do Chrome ou onde precisar, só não use Android Studio. O resultado só é computado conforme requisitado, ou seja não fica lá ocupando espaço da sua memória. Tipos de dados em Haskell: Bool: o basicão, True e False Char: contém todos os caracteres no Sistema Unicode String: array de Char como sempre, nada muda =P Int: precisão fixa em 64 bits Integer: vixi, um int do tamanho que você quiser ou puder Float: valores em ponto-flutuante de simples precisão Double: valores em ponto-flutuante de precisão dupla Temos como estrutura de dados: Listas, Tuplas =D O mais importante é função no Haskell, afinal ele é funcional =D
110 RONALDO DA COSTA TAVARES
111 SAMUEL ESDRAS NAVARRO DA SILVA Tipos de dados Int, Integer, Float, Double Notação para declarar soma :: Integer -> Integer -> Integer soma x y = x + y deve ser lido assim: “a função soma recebe (::) um tipo inteiro (Integer) seguido de (->) outro tipo inteiro e retorna (último ->) um tipo inteiro”. Funções x Haskell: f(x) = f x f(x, y) = f x y f(g(x)) = f(g(x)) Listas: data [a] = [] | a : [a] → uma das principais estruturas em linnguagens funcionais faixa de valores: [1..10] lista infinita: [0, 2] Duas instruções equivalentes: let s1 = "Ola mundo!" let s2 = ['O', 'l', 'a', ' ', 'm', 'u', 'n', 'd', 'o', '!'] Exemplos de funções: impar :: Integral a => a -> Bool impar n = n `mod` 2 == 1 quadrado :: Num a => a -> a quadrado n = n*n E existem diversas operações com lista (ver documentação) Convenções: Os nomes das funções e seus argumentos devem começar com uma letra minúscula e seguida por 0 ou mais letras, maiúsculas ou minúsculas, dígitos, underscore, e aspas simples Regra de layout: espaçamento é importante no haskell, ficar atento a identação
75 SERGIO MARACAJA JUNIOR
114 TAMIRES CHRISTYNE DA SILVA
117 VICTOR LOURENCO BORGES Paradigma funcional possuis 3 características principais: - Recursividade: ao invés de laços iterativos - Funções Puras: não causam efeitos colaterais (mudanças em vars globais, leitura/escrita de dados). Numa função pura, uma mesma entrada sempre resultará numa mesma saída. Se uma função pura passar a chamar uma impura, ela será impura também - Avaliação Preguiçosa: gera uma promessa de execução (thunk) para uma expressão, que será avaliada apenas se necessário. Ao contrário de outras linguagens onde os parâmetros da chamada de uma função são pré-calculados, em haskell substitui-se a expressão da função nos argumentos. Assim, argumentos não utilizados não serão calculados. Cálculo Lambda O que é computável? O que pode ser calculado pelo método lambda ou pela máquina de Turing. Um programa para decidir se o outro para não é O mínimo necessário para uma linguagem computável são funções sintaxe: \ parâmetro -> e (aplicação) O parâmetro pode ser uma outra função escopo: \x -> e a aplicação (e) de \x é o escopo de x (onde x está visível) ocorrências de x em em e está ligada por \x em \x y -> y, x está livre se e não tem variáveis livres, então e é uma expressão fechada semântica: podemos reescrever termos lambda com: passa alpha: renomeia um parâmetro passo beta: chama uma função: (\x -> x) 2 é o mesmo que passar 2 como argumento para \x, e substituir as ocorrências de x. Então \x -> 2 = 2. forma normal: se uma expressão lambda não tiver nenhum redex (redução por aplicação de função), ela está irredutível com o combinador omega, a substituição resulta na própria expressão original (ciclo sem fim) Através do cálculo lambda, conseguimos representar: booleanos, números, operações, e recursão. Em linguagens funcionais, usamos recursão ao invés de laços Combinador Y O combinador Y retorna um ponto fixo para qualquer função lambda. Desta forma, conseguimos fazer a chamada recursiva dentro das expressões.
118 VICTOR SANTANA RIBEIRO
119 VINICIUS DE OLIVEIRA CAMPOS DOS REIS
120 VINICIUS LOURENCO DA SILVA O cálculo lambda é baseado em funções e aplicado usando atribuições de nomes e substituições. Apesar de usarmos laços, booleanos, condicionais, etc, só precisamos de funções para programar de acordo com o cálculo lambda. O programa é definido por variáveis, funções lambdas e aplicações dessas funções. Expressões fechadas são expressões que não possuem variáveis livres (\x -> x). Formal normal é uma expressão que não tem nenhum redex, ou não pode ser reduzida. Combinadores omega, são funções que a cada passo de redução voltam a eles próprios, portanto, é impossível chegar na forma normal. Em haskell os códigos são concisos e declarativos, imutáveis, não possui laços de repetição, é tudo feito a partir de funções recursivas. Funções de alta ordem são funções que recebem funções como parâmetros, são utilizados tipos polimórficos, com funções genéricas. e possui avaliação preguiçosa, ou seja, só é computado o valor que realmente vai ser usado a diante. Os nomes de função devem ser começados com letra minúscula com camel case, para listas existe uma convenção de adicionar um s ao final do nome da lista, por exemplo, uma lista de elementos x, vira xs, os espaços no haskell são essenciais assim como em python e UTILIZE ESPAÇOS ao invés de tab
121 VITOR RUBENS SNIQUER LEAO MARTINS
116 VITTORIA ARIEL DOS SANTOS BOROTTO ate a aula 4.5
123 WALTER OSCAR TRUJILO
124 WESLEY AXEL DE BARROS Resumo sobre a atividade 02 de paradigmas da computação: Atividade simples, com a intuição de colocar em pratica todo o conhecimento que foi dado sobre Haskell até o momento. Foi pedido para que modificassem as funções escritas no arquivo src/Exercicios.hs Foram funções simples e outras um pouco mais complexas, com manipulação de valores, impressão em terminal com Strings, construção e manipulação de listas e verificação de resultados. Cada função com sua nota definida conforme a dificuldade da mesma. Modificando as funções conforme o enunciado das mesmas, e realizado os testes via stack gchi para verificar se as mesmas estavam funcionando, realizei o stack test que verificou que algumas funções não passaram devido problema com caracteres na String. Após alterar e realizar o stack test novamente, todos os testes passaram. para a função somaDigitosSeis utilizei essa função para o conseguir os digitos de um inteiro em uma lista https://stackoverflow.com/questions/3963269/split-a-number-into-its-digits-with-haskell
125 WESLEY BATISTA SOARES Cálculo Lambda foi criado por Alonzo Church na década de 1930. Podemos dizer que o Cálculo Lambda utiliza apenas funções para descrever computação. A sintaxe do Cálculo Lambda é composta por 3 elementos, que são: variáveis, definição de funções e aplicação de funções. Para o escopo de uma variável, ela pode estar ligada (dentro de uma abstração) ou livre (não está dentro de uma abstração). Caso uma expressão não tenha variáveis livres, essa expressão é chamada de expressão fechada (ou combinadores). A linguagem de progração funcional Haskell tem como características códigos concisos e declarativos. Suas variáveis são imutáveis (não podem receber novos valores). Para implementar laços em Haskell, devemos usar funções recursivas. Haskell possui funções de alta ordem (funções que recebem outras funções como parâmetro) e tipos polimorficos. Haskell utiliza avaliação preguiçosa para os cálculos, assim podemos ter listas infinitas (já que serão calculadas somente quando necessário). Funções são definidas com o nome da função, seguida dos parâmetros. Tuplas são sequências finitas, podendo conter tipos diversos, entre parênteses. Guards são uma forma alternativa ao if else.
45 WILLIAM DE SOUZA GOMES Aprendi que Haskell é uma linguagem fortemente tipada. Com isso devemos colocar na declaração das funções o tipo, como por exemplo na função soma dois numeros inteiros e devolve um número inteiro. Soma :: Innteger -> Innteger -> Innteger Haskell também trabalha com avaliação preguoçosa, isso é bom, porque nos permite criar uma lista infinita como exemplo, [1..], isso é permitido pq em Haskell só será avaliada em tempo de execxução e quando for necessário o uso dos elementos É possível com Haskell utilizar diversas manipulações com listas, conhecida como List Comprehension. Dentre as possibilidades podemos utilizar uma variável que será atribuida na lista a cada iteração, uma lista e um condicional. Segue um exemplo abaixo [x^2| x <- as, x `mod`2 == 0] ou seja, para todos os elementos de uma lista as pegue esse valor e eleve ao quadrado apenas os elementos que sejam par.
126 WILLIAM SENA SILVA
127 WILLIAN CORTEZ Semana 2 Na aula da semana 2, foi passado pelos conceiotas básicos do Haskell, no Hello World foi demonstrado os conceitos do main, IO(). Os requisitos dos nomes devem ser sempre minusculas para facilitar a digitação. Para o nome da lista, é acrescentado o s, exemplo, uma lista x ficaria xs. O layout do código é importante, bem parecido com Python, fazendo o uso rigoroso da indentação. Tipo de Dados, todos os tipos começam com letra maiuscula, existe os convencionais Int, Bool, Double, Float, String, Integer Lista são sequências de elementos do mesmo tipo agrupados por colchetes e separados por vírgula. Tuplas são sequências finitas de componentes, contendo zero ou mais tipos diferentes. Funções são mapas de argumentos de um tipo para resultados em outro tipo. O tipo de uma função é escrito como T1 -> T2, ou seja, o mapa do tipo T1 para o tipo T2: not :: Bool -> Bool even :: Int -> Bool Para escrever uma função com múltiplos argumentos, basta separar os argumentos pela ->, sendo o último o tipo de retorno: soma :: Int -> Int -> Int soma x y = x + y