Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

41
Haskell

Transcript of Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Page 1: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Haskell

Page 2: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Alunos: Bruno Triani

Ricardo Adão

Aloisio Cardozo

Page 3: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Nomeada em homenagem ao lógico Haskell Brooks Curry, como uma base para linguagens funcionais.

É baseada no lambda calculus.

Haskell é funcional (isto é, tudo é feito com chamadas de funções), estática, implicitamente tipada (os tipos são checados pelo compilador, porém não é necessário declará-los), preguiçosa (nada é feito até que se precise).

Haskell B. Curry (1900 - 1982)

Page 4: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

História do Haskell

O conceito de avaliação preguiçosa já estava difundido nomeio acadêmico desde o final da década de 1970. Esforçosnessa área incluíam técnicas de redução de grafo e apossibilidade de uma mudança radical na arquitetura de vonNeumann.Conferência Functional Programming Languages andComputer Architecture (FPCA '87) - setembro de 1987criação de um comitê com o objetivo de construir umpadrão aberto para tais linguagens.

Page 5: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

História do Haskell

A primeira reunião do comitê - janeiro de 1988,metas da linguagem:linguagem e fácil ensino,completamente descrita através de uma sintaxe esemântica formaldisponível livremente.Primeira versão 1 de abril de 1990; versão 1.1 agosto de1991, a versão 1.2 em março de 1992, versão 1.3 maio de1996 versão 1.4 em abril de 1997.Haskell 98, janeiro de 1999 - versão mínima, estável eportável da linguagem e o biblioteca para ensino. Essepadrão sofreu uma revisão em janeiro de 2003.

Page 6: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

História do Haskell

A linguagem continua evoluindo, sendo as implementaçõesHugs e GHC consideradas os padrões.A partir de 2006 começou o processo de definição de umsucessor do padrão 98, conhecido informalmente por Haskell′("Haskell Prime").

Page 7: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

O que é programação funcional?

C, Java, Pascal, Ada, e assim por diante, são linguagens imperativas. São "imperativas" no sentido em que consistem em uma seqüencia de comandos, que são executados estritamente um após o outro. Haskell é uma linguagem funcional. Uma linguagem funcional é uma única expressão, que é executada avaliando essa expressão. Qualquer um que já usou uma planilha eletrônica, tem experiência em programação funcional. Em uma planilha, especificamos o valor de cada célula, em função dos valores de outras células. O foco está em "o quê" deve ser computado, e não "como" deve ser computado. Por exemplo:

-nós não especificamos a ordem em que as planilhas devem ser computadas, ao invés disso, nós temos garantia que a planilha será calculada em uma ordem que respeite suas dependências.

Page 8: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

-nós não dizemos à planilha como alocar sua memória - melhor, esperamos apresentar-nos com um plano aparentemente infinito de células, e alocar na memória somente as células que estão realmente em uso.

-na maioria das vezes, avaliamos o valor das células por uma "expressão" (cujas partes podem ser avaliadas em qualquer ordem), melhor que por uma "seqüência de comandos" que compute seu valor.

O cálculo lambda  é uma coleção de diversos sistemas formais baseados em uma notação para funções inventada por Alonzo Church em 1936  com o intuito de capturar os aspectos mais básicos da maneira pela qual operadores ou funções podem ser combinados para formar outros operadores.

O cálculo lambda serve como uma ponte entre linguagens funcionais de alto nível e suas implementavéis de baixo nível. Raízes para a apresentação do cálculo lambda como uma linguagem intermediária: uma linguagem extremamente simples, consistindo de somente algumas poucas construções sintáticas e de uma semântica simples.

Page 9: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Uma implementação do cálculo lambda necessita somente suportar algumas construções simples.

A sua semântica simples nos permite analisar facilmente a correção de sua implementação.

Trata-se de uma linguagem expressiva, a qual é suficientemente poderosa para expressar todos os programas funcionais e, por conseguinte, todas as funções computáveis. Isto significa que, se uma boa implementação do cálculo lambda é disponível, pode-se implementar qualquer linguagem funcional através da implementação de um compilador desta para o cálculo lambda.

Page 10: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Estilo FuncionalEstilo ImperativoEstilo Imperativo X Estilo Funcional

programa: sequência de comandos que transformam variáveis

base: variáveis, comandos, procedures

execução: conceito de sequência

variáveis: mudanças de estado, alteração por atribuição

estado: implícito, modificado por atribuições

componentes de primeira classe: variáveis

programa: é uma funçao composta por funções mais simples

base: expressões, funções

execução: baseada em recursividade

nomes identificam valores permanentes (const), transparência referencial

estado: explícito, modificado por funções

componentes de primeira classe: funções

Page 11: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Metalinguagem de Haskell:

Em haskell, a metalinguagem é encontrada no uso de comentários. Alguns tokens léxicos encontrados são apresentados a seguir:

•Comentários:

Comentário de bloco: é feito pelos delimitadores {- e -}. Comentário de linha: o início do comentário é definido pelos sinais menos duplo (--).

•Definição de condicionais:

Determinamos condicionais para determinar qual o fluxo de execução atende melhor as nossas necessidades. Nesse caso, o escopo é definido pelo uso de delimitadores como o then:

if<condicao> then <comando> else<comando2> | <condicao1>=<comando1>| <condicao2>=<comando2>

Page 12: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Entrando no mundo do Haskell

Passo 1: Baixar e Instalar o compilador- GHC Compilador e interpretador (GHCi). (http://www.haskell.org/ghc/)- Hugs Unicamente interpretador. Portátil e mais leve do que oGHC.(http://www.haskell.org/hugs/)

Page 13: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Passo 2 : Iniciar

1. Abra um terminal2.- Se você instalou o GHC, digite ghci(o nome do executáveldo interpretador GHC) no promt de comando.- Se você instalou Hugs, digite hugs.

Page 14: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Passo 3: Escreva o primeiro programa

Prelude> “Hello, World!”“Hello, World!”

O Haskell imprimiu o resultado.

>>> Você pode tentar uma variação para imprimir diretamentea saída padrão:

Prelude> putStrLn “Hello World”Hello World

Page 15: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Usando um compilador Haskell, você pode compilar o código parapara um executável standalone . Crie um arquivo fonte hello.hscontendo:

main = putStrLn "Hello, World!"E compile o arquivo com:$ ghc -o hello hello.hs>>> Você pode então correr o executável (./hello no Unix hello.exee no Windows):$ ./helloHello, World!

Page 16: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Expressões simples

Você pode digitar a maioria das expressões matemáticas diretamente no ghci. Prelude> é o prompt padrão do GHCi.

Prelude> 3 * 5

15 Prelude> 4 ^ 2 - 1 15 Prelude> (1 - 5)^(3 * 2 - 4) 16

Strings estão em aspas duplas. Você pode concatená-las usando ++.

Prelude> "Hello" "Hello" Prelude> "Hello" ++ ", Haskell" "Hello, Haskell"

Page 17: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

As chamadas das funções são feitas colocando se os argumentos diretamente depois da da função. Não existem parênteses para a chamada:

Prelude> succ 5 6 Prelude> truncate 6.59 6 Prelude> round 6.59 7 Prelude> sqrt 2 1.4142135623730951 Prelude> not (5 < 3) True Prelude> gcd 21 14 7

Page 18: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

I/O (Entrada / Saída)

Ações de I/O podem ser usadas para ler e escrever a partir do próprio console. Algumas são descritas abaixo.

Prelude> putStrLn "Hello, Haskell" Hello, Haskell Prelude> putStr "No newline" No newlinePrelude> print (5 + 4) 9 Prelude> print (1 < 2) True

As funções putStr e putStrLn tem strings como saída para o terminal. A função print gere saída seja qual for o tipo. (Se você usar print para uma string, ela terá aspas duplas.) Se você precisar de múltiplas ações de I/O numa única expressão, você pode usar o bloco do. As ações são separadas por ponto e vírgula.

Prelude> do { putStr "2 + 2 = " ; print (2 + 2) } 2 + 2 = 4 Prelude> do { putStrLn "ABCDE" ; putStrLn "12345" } ABCDE 12345

Page 19: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

A leitura pode ser feita com o getLine (no qual retorna uma String) ou readLn (no qual retorna qualquer tipo de valor que você deseje). O símbolo <- é usado para atribuir um nome ao resultado da ação I/O. Prelude> do { n <- readLn ; print (n^2) } 4 16(O 4 era a entrada. O 16 foi o resultado)

Existe também uma outra maneira de escrever blocos. Se você não colocar chaves e ponto e virgula, a identação se torna relevante. Isto não funciona tão bem no ghci, por isso é recomendado que ponha o código num arquivo (ex.: teste.hs) e compile.

main = do putStrLn "What is 2 + 2?"

x <- readLn if x == 4 then putStrLn "You're right!" else putStrLn "You're wrong!"

Page 20: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Uma forte característica da linguagem Haskell é sua “tipagem” (strongly typed), isto é, é sempre possível determinar o tipo de uma determinada entidade. Em contra-ponto podemos fazer uma analogia com linguagens sem tipos, ou melhor, linguagens onde todas entidades partilham de um mesmo tipo, como é o caso de LISP. Podemos citar os seguintes tipos base de Haskell no slide seguinte:

Page 21: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Tipo unitário: é uma implementação do conjunto um, sendo assim, todos os demais tipos derivam desse.

Tipo lógico (bool): valores lógicos, podendo assumir como valores: true, false, otherwise (= true). Podem ser submetidos aos seguintes operadores: && (conjunção); || (disjunção); not (negação).

Tipo caracter (char): valores Unicode do nosso alfabeto, podendo assumir como valores símbolos da tabela Unicode (16bits).

Tipo numérico: valores numéricos, inteiros (int, integer), e reais (float, double).

Listas: conjunto das seqüências finitas, eventualmente vazias, de elementos de um dado tipo. Dentre todos operadores podemos citar: last – retorna último elemento de uma lista; init – retorna o primeiro elemento de uma lista; ++ - realiza a concatenação entre duas listas. Seqüências de caracteres (Strings): podem ser considerados como uma lista de caracteres.

Page 22: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Utilizamos o comando type para setar o interpretador a mostrar informações sobre o tipo das expressões manipuladas no decorrer da seção. A avaliação de uma expressão por parte do interpretador é realizada normalmente (esquerda para direita). Podendo o mesmo ser setado para que informe dados estatísticos a respeito das alterações realizadas (:set +s). 

Page 23: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

A definição de funções deve ser realizada em um novo arquivo, o qual deverá possuir a extensão “.hs” através do comando load <file> as funções declaradas são disponibilizadas.

A definição de uma função é realizada através da escrita de uma equação, a qual irá determinar o comportamento da mesma. Deve-se obedecer a seguinte sintaxe: 

<nome_da_funcao> <argumento> = <expressão>  A linguagem Haskell não suporta mais de um argumento. Esse

problema pode ser resolvido agrupando seus argumentos em um n-duplo: 

<funcao> :: (Int, Int) -> Int <funcao> <arg1, arg2> = <command> 

Page 24: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Ao invés de usar equações para definir funções, pode-se utilizar uma notação lambda, em que a função não precisa ter um nome. Por exemplo, a função sucessor :: Int -> Int  sucessor x = x+1 poderia ser definida como lx. x+1 na notação lambda, ou \x -> x + 1 em Haskell. Temos então Haskell > (\x -> x + 1) 10 11. Da mesma maneira a função soma poderia ter sido definida da seguinte maneira:

soma = \ x y -> x + y O operador de composição de funções é definido utilizando a

sintaxe lambda:  (.) :: (u -> v) -> (t -> u) -> (t -> v) f . g = \x -> f (g x) 

Page 25: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Tipos Simples:

Até agora, nenhuma declaração de variável foi mencionada. Isto é porque Haskell faz dedução de tipos. Você geralmente não tem que declarar tipos a não ser que você queira. Se quiser declarar ponha :: para tal. Veja abaixo:

Prelude> 5 :: Int

5 Prelude> 5 :: Double 5.0

Tipos (e “classes tipo”, veremos mais adiante) sempre iniciam com letras maiúsculas em Haskell. Variáveis sempre iniciam com letras minúsculas Isto é uma regra, não uma convenção da linguagem.

Você pode também perguntar ao ghci que tipo foi escolhido para alguma coisa. Isto é útil porque geralmente você não precisa declarar seus tipos.

Page 26: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Prelude> :t True True :: Bool Prelude> :t 'X' 'X' :: Char Prelude> :t "Hello, Haskell" "Hello, Haskell" :: [Char]

(Como é notado neste caso, [Char] é outra maneira de dizer String.)

Page 27: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Um pouco mais interessante, agora com número.

Prelude> :t 42 42 :: (Num t) => t Prelude> :t 42.0 42.0 :: (Fractional t) => t Prelude> :t gcd 15 20 gcd 15 20 :: (Integral t) => t

Estes tipos usam “classes tipo”. Quer dizer:42 pode ser usado como um tipo numérico

qualquer. (Este é o porque de anteriormente eu ter declarado 5 como Int ou Double).

42.0 pode ser qualquer tipo fracionário, mas não um tipo inteiro.

gcd 15 20 (no qual é uma chamada de função) pode ser qualquer tipo inteiro, mas não um tipo decimal.

Page 28: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Existem cinco tipos numéricos no Haskell “prelude” (a parte da biblioteca que existe sem ter que importar nada):

Int é um inteiro com no máximo 30 bits de precisão.

Integer é um inteiro sem limitação de precisão.

Float precisão simples de ponto flutuante.

Double precisão mais aprimorada de ponto flutuante.

Rational tipo fracionário, sem nenhum erro de arredondamento.

Todos os cinco são instancias da classe tipo Num. Os dois primeiros são instancias do Integral, e os outros três são instancias do Fractional.

Page 29: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Dados estruturados

Tipos básicos de dados podem ser combinados em duas maneiras: listas, na qual colocamos [entre colchetes], e tuplas que ficam (entre parênteses).

Listas são usadas para agrupar multiplos valores do mesmo tipo.

Prelude> [1, 2, 3] [1,2,3] Prelude> [1 .. 5] [1,2,3,4,5] Prelude> [1, 3 .. 10] [1,3,5,7,9] Prelude> [True, False, True] [True,False,True]

Strings são apenas listas de caracteres.

Prelude> ['H', 'e', 'l', 'l', 'o'] "Hello"

Page 30: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

O operador : (dois pontos), coloca um item no início da lista. Prelude> 'C' : ['H', 'e', 'l', 'l', 'o'] "Chello"

Tuplas mantem um numero fixo de valores, no qual pode haver diferentes tipos.

Prelude> (1, True) (1,True) Prelude> zip [1 .. 5] ['a' .. 'e'] [(1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e')]

O ultimo exemplo, é usado zip, uma função da biblioteca que transforma duas listas em uma tupla.

Page 31: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Os tipos que provavelmente esperamos.

Prelude> :t ['a' .. 'c']

['a' .. 'c'] :: [Char] Prelude> :t [('x', True), ('y', False)] [('x', True), ('y', False)] :: [(Char, Bool)]

As listas são muitos usadas em Haskell. Abaixo algumas funções úteis.

Prelude> [1 .. 5] [1,2,3,4,5] Prelude> map (+ 2) [1 .. 5] [3,4,5,6,7] Prelude> filter (> 2) [1 .. 5] [3,4,5]

Prelude> fst (1, 2) 1 Prelude> snd (1, 2) 2 Prelude> map fst [(1, 2), (3, 4), (5, 6)] [1,3,5]

Page 32: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Definições de funções

Como já demonstrado anteriormente, uma ação I/O, chamada main:

main = do putStrLn "What is 2 + 2?"

x <- readLn if x == 4 then putStrLn "You're right!" else putStrLn "You're wrong!" Agora, temos uma função chamando outra função: factorial n = if n == 0 then 1 else n * factorial (n - 1) main = do putStrLn "What is 5! ?" x <- readLn if x == factorial 5 then putStrLn "You're right!" else putStrLn "You're wrong!"

Page 33: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Compilando de novo com ghc-make Teste.hs. E,

$ ./Test What is 5! ? 120 You're right!

Temos um função, podendo ser chamada como fatorial 5 sem precisar usar parênteses Agora perguntamos ao ghci o tipo.

$ ghci Test.hs << GHCi banner >> Ok, modules loaded: Main. Prelude Main> :t factorial factorial :: (Num a) => a -> a

Tipos de funções são escritas com um tipo de argumento, depois ->, depois o tipo do resultado. A função fatorial também pode ser simplificada sendo escrita com analise de caso. factorial 0 = 1factorial n = n * factorial (n - 1)

Page 34: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Sintaxes convenientes

Algumas outras sintaxes que podem ser úteis.

secsToWeeks secs = let perMinute = 60 perHour = 60 * perMinute perDay = 24 * perHour perWeek = 7 * perDay in secs / perWeek

A expressão let define nomes temporários.

classify age = case age of 0 -> "newborn" 1 -> "infant" 2 -> "toddler" _ -> "senior citizen"

Page 35: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Quicksort in C// To sort array a[] of size n: qsort(a,0,n-1) void qsort(int a[], int lo, int hi) { { int h, l, p, t; if (lo < hi) { l = lo; h = hi; p = a[hi]; do { while ((l < h) && (a[l] <= p)) l = l+1; while ((h > l) && (a[h] >= p)) h = h-1; if (l < h) { t = a[l]; a[l] = a[h]; a[h] = t; } } while (l < h); a[hi] = a[l]; a[l] = p;

qsort( a, lo, l-1 ); qsort( a, l+1, hi ); } }

Page 36: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Quicksort in Haskell

qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)

A primeira linha lê-se: "Quando você classifica uma lista vazia ( [] ), o resultado é uma outra lista vazia".

A segunda linha diz: "Para ordenar uma lista cujo primeiro elemento é chamado x e o resto do que é chamado xs , classificar os elementos de xs , que são menos de x , classificar os elementos de xs , que são iguais ou superiores a x , e concatenar ( + + ) os resultados, com x colada no meio.

Page 37: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

Programa Exemplo:-- script tabela-- banco de dados das notas:aluno :: Int -> Floataluno 1 = 7.5aluno 2 = 10aluno 3 = 9aluno 4 = 6.3-- (...)tabela :: Int -> Stringtabela n = cabeçalho ++ imprimeAlunos n ++

imprimeMedia ncabeçalho :: Stringcabeçalho = “Aluno Nota\n”

Page 38: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

imprimeAlunos :: Int -> StringimprimeAlunos 1 = imprimeAluno 1imprimeAlunos n = imprimeAlunos (n-1) ++ imprimeAluno nimprimeAluno :: Int -> StringimprimeAluno n = show n ++ “ “ ++ show (aluno n) ++ “\n”imprimeMedia :: Int -> StringimprimeMedia n = “\n” ++ “Média da Turma: “ ++ show

(media n)soma :: Int -> Floatsoma 1 = aluno 1soma n = aluno n + soma (n-1)media :: Int -> Floatmedia n = (soma n) / (fromInt n)

Page 39: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

procuraValor :: Arvore -> Int ->Bool

procuraValor Null num = False

procuraValor (Node valor esq dir) num

| valor == num = True

| otherwise = False || (procuraValor esq num) ||

(procuraValor dir num)

Page 40: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

ABN AMRO Amsterdã, Holanda ABN AMRO é um banco internacional sediado em Amsterdã. É usado

para medir os riscos de investimentos dos portifólios.

AT&T Haskell é usado na divisão de segurança para

automatizar processos de reclamações sobre abusos na internet.

Haskell tem um amplo uso comercial, de aeronaves e defesa, finanças, complementos web, empresas de design

de hardware, etc.

Page 41: Haskell. Alunos: Bruno Triani Ricardo Adão Aloisio Cardozo.

• www.haskell.org• www.haskell.edu/haskell• www.haskell.org/haskell-history.html• http://pt.wikipedia.org/wiki/

Haskell_(linguagem_de_programação)• http://www.haskell.org/haskellwiki/

Learn_Haskell_in_10_minutes• http://hackage.haskell.org/platform/• http://www.haskell.org/ghc/

download_ghc_6_12_1.html• http://www.macs.hw.ac.uk/~dubois/

ProgramacaoHaskell.pdf