• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Unidade7 1
 

Unidade7 1

on

  • 1,110 views

 

Statistics

Views

Total Views
1,110
Views on SlideShare
1,110
Embed Views
0

Actions

Likes
0
Downloads
13
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Unidade7 1 Unidade7 1 Presentation Transcript

    • Programação Funcional comHaskellProf. Iális CavalcanteFonte: Prof. Dr. Francisco VieiraEngenharia da Computação – UFC/Sobral
    • 0. Sumário Editor WinHugs Nomes Avaliação de funções Definições dos tipos das funções Associatividade Tipos de Dados Escopo Definições Locais Tratamento de Exceções Prova de Programas
    • 1. Editor WinHugs :? – comando Help (o princípio de tudo):? 2 + 3 <enter>5:? (1 * 6) == (3 ‘div’ 5) <enter>False:? maximo (quadrado 2) 1 <enter>4 Palavras reservadas: case else infix module type class hiding infixl of where data if infixr renaming default import instance then deriving in let to
    • 1. Editor WinHugs (exemplo.hs){-##############################################exemplo.hsEste arquivo eh um exemplo de um arquivo .hs. Os programas aqui mostrados podem ser conseguidos na pagina de Haskell: http://www.haskell.org que contem links importantes para quem quer fazer parte de listas de usuarios de Haskell em todo mundo.###############################################-}resposta :: Int -- Uma constante inteiraresposta = 42novalinha :: Charnovalinha = ’n’sim :: Boolsim = True
    • 1. Editor WinHugs (exemplo.hs)maior :: Boolmaior = (resposta > 71)quadrado :: Int -> Intquadrado x = x*xtodosIguais :: Int -> Int -> Int -> BooltodosIguais n m p = (n == m) && (m == p){-##########################-}
    • 1. Editor WinHugs Principais comandos de HugsComando Ação realizada:? Aciona o help:e Chama o script atual:e exemplo.hs Edita o arquivo exemplo.hs:l exemplo.hs Carrega o script exemplo.hs e limpa outros arquivos carregados:a exemplo.hs Carrega o script exemplo.hs sem limpar os outros arquivos:q Termina a sessão Ver Prelude.hs; Roteiro: ◦ Criar código-fonte: *.hs ◦ Carregar no WinHugs (:l ou :load) ◦ Executar suas funções
    • 1. Editor WinHugs Comentários no código: ◦ com “- -”, que representa um comentário até o final da linha corrente; ◦ ou com os símbolos “{-” e “-}” envolvendo todo o texto a se tornar um comentário, que podem englobar até várias linhas Uma função, em Haskell, pode ser representada graficamente por uma caixa que recebe um ou mais parâmetros como entrada, processa estes parâmetros e constrói um resultado que é único. A aplicação de uma função consiste no processo se colocar os parâmetros na função. resultado parâmetro(s) função
    • 2. Nomes Os nomes em Haskell são sensíveis a caracteres ◦ as letras maiúsculas são distintas das letras minúsculas. Os nomes, também chamados de identificadores, devem ser iniciados ◦ sempre por uma letra maiúscula, se for um tipo, ◦ ou minúscula, se for uma variável ou o nome de alguma função. Estes nomes são seguidos, opcionalmente, por uma seqüência de letras maiúsculas ou minúsculas, dígitos, sublinhado ou acentos agudos. As palavras reservadas da linguagem são sempre escritas em letras minúsculas.type Par = (Int, Int)somaAmbos :: Par -> IntsomaAmbos (primeiro, segundo) = primeiro + segundo
    • 3. Avaliação de funções leftmost-outermost avaliação preguiçosa (lazy evaluation) ◦ só avalia uma expressão se ela for realmente necessária e no máximo uma vez (avaliação curto-circuito). Testar:todosIguais (quadrado 3) resposta (quadrado 2)
    • 3. Avaliação de funções (cont.) todosIguais (quadrado 3) resposta (quadrado 2)todosIguais (quadrado 3) resposta (quadrado 2)= ((quadrado 3) == resposta) && (resposta == (quadrado 2))= ((3 * 3) == resposta) && (resposta == (quadrado 2))= (9 == resposta) && (resposta == (quadrado 2))= (9 == 42) && (42 == (quadrado 2))= False && (42 == (quadrado 2)) (utilizando lazy evaluation)= False
    • 4. Definições dos tipos das funções Um tipo é uma coleção de valores onde todos eles têm as mesmas características. ◦ Por exemplo, os números inteiros, os quadros, os caracteres, os strings de caracteres, etc. Em Haskell, se incentiva que todos os parâmetros de entrada e a saída tenham seus tipos explicitados pelo programador como uma forma de facilitar a checagem de tipos e de evitar muitos erros de programação. ◦ No entanto, os tipos podem também ser inferidos a partir das definições das funções. + :: Int -> Int -> Int e escala :: Quadro -> Int -> Quadro Int Int Int + Quadro Quadro escala Int
    • 5. AssociatividadePrioridade Assoc. à esquerda Não associativa Assoc. `a direita 9 !, !!, //, > . > >>= . 8 **, ˆ, ˆˆ 7 % , /, ‘div‘, ‘mod‘, ‘rem‘, ‘quot‘ 6 +, - :+ 5 :, ++, > + > 4 /=, <, <=, = =, >, >=, ‘elem‘, ‘notElem‘ 3 && 2 || 1 := 0 $
    • 5.1. Testes eZero :: Int -> Bool eZero 0 = True eZero _ = False fat :: Int -> Int fat 0 = 1 fat n = n * fat (n -1)
    • 6. Tipos de dados Admite: ◦ tipos primitivos e; ◦ tipos estruturados; tipos definidos pelo usuário a partir de outros tipos. Os tipos primitivos: ◦ inteiro (Int ou Integer), booleano (Bool), caractere (Char), cadeia de caracteres (String), ponto flutuante (Float ou Double) e o tipo lista.
    • 6.1. Tipo Inteiro Os valores do tipo Integer são representados com o dobro da quantidade de bits necessários para representar os valores do tipo Int. Operadores aritméticos para valores dos tipos +, * adição e multiplicação ˆ exponenciação - subtração (infixa) e inversor de sinal (prefixa) div divisão inteira (prefixa), ou ‘div‘ (infixa) mod módulo (prefixa), ou ‘mod‘ (infixa) abs valor absoluto de um inteiro negate troca o sinal de um inteiro Operadores relacionais: Int −> Int −> Bool >, >=, ==, / =, <=, <
    • 6.1. Tipo Inteiro Exemplo: série de fibonacci0, 1, 1, 2, 3, 5, 8, 13, ...fibonacci :: Int -> Intfibonacci 1 = 0fibonacci 2 = 1fibonacci n = fibonacci(n-1) + fibonacci(n-2)mdc :: Int -> Int -> Intmdc n m |m == n = n |m > n = mdc m n |otherwise = mdc (n - m) m
    • 6.2. Tipo Bool Os únicos valores booleanos são True e False Função Nome Tipo && and && :: Bool − > Bool − > Bool || or || :: Bool − > Bool − > Bool not inversor not :: Bool − > Bool A função Ou exclusivoexOr :: Bool -> Bool -> BoolexOr True x = not xexOr False x = x
    • 6.3. O tipo caractere São literais escritos entre aspas simples. Caracteres especiais para utilizações específicas ‘t’ tabulação ‘” aspas simples ‘n’ nova linha ‘”’ aspas duplas ‘’ uma barra invertida ‘34’ ? funções pré-definidas em Haskell feitas para converter caracteres em números e vice-versa. ◦ toEnum :: Int − > Char ◦ fromEnum :: Char − > Int
    • 6.4. O tipo cadeia de caracteres Os criadores de Haskell admitiram duas formas para este tipo: ◦ É um tipo predefinido; podem ser escritos entre aspas duplas “Constantino” ◦ Ou pode ser considerado como uma lista de caracteres Descrita como type String = [Char] usando a notação de lista de caracteres (entre aspas simples). [’C’, ’o’, ’n’, ’s’, ’t’, ’a’, ’n’, ’t’, ’i’, ’n’, ’o’].
    • 6.4. O tipo cadeia de caracteres Exemplos: ◦ “baleia”− > baleia ◦ −> ◦ “99a116”− > cat ◦ “jeri”++ “qua”++ “quara”− > jeriquaquara Exercício: ◦ Defina uma função charToName :: Char − > Int que converte um dígito em seu valor (por exemplo, ‘8’ em 8). O valor de um caractere não dígito deve ser 0 (zero).
    • 6.5. O tipo ponto flutuante Os valores do tipo ponto flutuante (números reais) pertencem aos tipos Float ou Double; A diferenças entre os valores destes tipos se verificam na quantidade de bits necessários para representá-los.
    • 6.6. Os tipos de dados estruturados Os tipos estruturados são construídos a partir de outros tipos, sejam eles primitivos ou estruturados. Tipo produto cartesiano: ◦ representado em Haskell pelas tuplas; ◦ representado registros ou estruturas em linguagens imperativas ◦ o tipo (t1, t2, ..., tn) consiste de tuplas de valores (v1, v2, ..., vn) onde v1 :: t1, v2 :: t2, ..., vn :: tn
    • 6.6. Os tipos de dados estruturados Exemplo: ◦ type Pessoa = (String, String, Int) ◦ maria :: Pessoa ◦ maria = ("Maria das Dores", "225-0000", 22) ◦ intP :: (Int, Int) ◦ intP = (35, 45) ◦ somaPar :: (Int, Int) -> Int ◦ somaPar (x, y) = x + y ◦ shift :: ((Int, Int), Int) -> (Int, (Int, Int)) ◦ shift ((a,b),c) = (a, (b,c))
    • 6.6. Os tipos de dados estruturados Mais exemplos: ◦ nome :: Pessoa -> String ◦ fone :: Pessoa -> String ◦ idade :: Pessoa -> Int ◦ nome (n, p, a) = n ◦ fone (n, p, a) = p ◦ idade (n, p, a) = a ◦ somaPar :: (Int, Int) -> Int Requer um argumento: tupla ◦ somaPar (a, b) = a + b Cuidado, são diferentes!!! ◦ somaDois :: Int -> Int -> Int ◦ somaDois a b = a + b Requer dois argumentos
    • 7. Escopo O escopo de uma definição é a parte de um programa na qual ela é visível e portanto pode ser usada. Em Haskell, o escopo das definições é todo o script.ehImpar, ehPar :: Int -> BoolehImpar 0 = FalseehImpar n = ehPar (n-1)ehPar 0 = TrueehPar n = ehImpar (n-1)
    • 8. Definições Locais Através de palavras reservadas: where, let, in, if, then, else, ...somaQuadrados :: Int -> Int -> IntsomaQuadrados n m = quadN + quadM where quadN = n * n quadM = m * mlet x = 3 + 2; y = 5 - 1 in x^2 + 2*x*y - y
    • 8. Definições Locais As definições locais são visíveis apenas na equação onde elas foram declaradas. As variáveis que aparecem do lado esquerdo também podem ser usadas em definições locais.maxq :: Int -> Int -> Intmaxq x y |sqx > sqy = sqx |otherwise = sqy where sqx = sq x sqy = sq y sq :: Int -> Int sq z = z * z
    • 8. Definições Locais As definições locais podem ser usadas antes que elas sejam definidas e também podem ser usadas em resultados, em guardas ou em outras definições locais. maxThreeOccurs :: Int -> Int -> Int -> (Int, Int) maxThreeOccurs n m p = (max, eqCount) where max = maxiThree n m p eqCount = equalCount max n m p maxiThree :: Int -> Int -> Int -> Int maxiThree a b c = maximo (maximo (a, b), c) equalCount :: Int -> Int -> Int -> Int -> IntequalCount val n m p equalCount val n m p= isN + isM + isP = isval n + isval m + isval p where where isN = if n == val then 1 else 0 isval :: Int − > Int isM = if m == val then 1 else 0 isval x = if x == val then 1 else 0 isP = if p == val then 1 else 0
    • 8.1 Cálculo Um exemplo bastante conhecido é o de encontrar as raízes reais de uma equação do segundo grau. Neste caso teremos como entrada a equação a * xˆ2 + b * x + c = 0. Para construirmos esta solução, a saída será a string “A equação 1.0 * x^2 + 5.0 * x + 6.0= 0.0 tem duas raízes reais e distintas: -2.0 e -3.0”. Para isto vamos construir duas funções, sendo uma para o caso da função ter duas raízes reais e distintas e a outra para o caso dela ter duas raízes reais e iguais.
    • 8.1 CálculoumaRaiz :: Float -> Float -> Float -> FloatumaRaiz a b c = -b / (2.0 * a)duasRaizes :: Float -> Float -> Float -> (Float, Float)duasRaizes a b c = (d + e, d - e) where d = -b/(2.0*a) e = sqrt (b^2 - 4.0*a*c)/(2.0*a)saida :: Float -> Float -> Float -> Stringsaida a b c = cabecalho a b c ++ raizes a b c
    • 8.1 Cálculocabecalho :: Float -> Float -> Float -> Stringcabecalho a b c = "A equacao nnt"++ show a ++ "*x^2 + " ++ show b ++ "*x + " ++ show c ++ " = 0.0" ++ "nntem "raizes:: Float -> Float -> Float -> Stringraizes a b c | b^2 > 4.0*a*c = "duas raizes reais e distintas: " ++ show f ++ " e " ++ show s | b^2 == 4.0*a*c = "duas raizes reais e iguais: " ++ show (umaRaiz a b c) | otherwise = "nenhuma raiz real " where (f, s) = duasRaizes a b c
    • 9. Tratamento de Exceções O tratamento de exceções é uma forma de se programar que previne a ocorrência de erros devido a entradas não previstas ◦ ao tempo em que indica quais as providências que o computador deve tomar no caso dessas entradas ocorrerem ◦ sem ter que necessariamente abortar o programa ou deixar que ele entre em loops infinitos até extinguir toda a memória. No caso da equação do segundo grau, quando a entrada para o coeficiente a for zero, não será possível a divisão de qualquer número por ele.umaRaiz a b c |(a /= 0.0) = -b/ (2.0 * a) |otherwise = error "umaRaiz chamada com a == 0"
    • 10. Prova de Programas Uma prova é uma argumentação lógica ou matemática para verificar se alguma premissa é ou não válida em quaisquer circunstâncias. Este tema tem importância fundamental na construção de programas, uma vez que deve-se ter a garantia de que o programa esteja correto e que ele resolva exatamente o problema para o qual foi codificado. No entanto, existe um dilema: aversão pela prova de programas. Por se acreditar que é uma técnica de fundamentação matemática e, portanto, teórica. A prova de programas em qualquer linguagem imperativa é realmente tediosa, no entanto, ela se torna quase natural em uma linguagem funcional como Haskell.
    • 10. Prova de Programas No entanto, um cuidado deve ser tomado, para que se evitem alguns erros de avaliação. A avaliação de uma expressão pode: ◦ parar e dar uma resposta (totalVendas 2). O valor da expressão é definido, ou ◦ nunca parar (totalVendas (-2)). O valor da expressão é indefinido. Qual o valor de 0*e?
    • 10. Prova de Programas Existem em Haskell três formas de se formalizar provas: a prova direta, a prova por casos e a prova por indução matemática. 10.1. Prova Direta ◦ A verificação da prova direta é feita pela aplicação das definições das funções.
    • 10.1. Prova Diretatroca :: (Int, Int) -> (Int, Int)troca (a, b) = (b, a)cicla, recicla :: (Int, Int, Int) -> (Int, Int, Int)cicla (a, b, c) = (b, c, a)recicla (a, b, c) = (c, a, b) troca (troca (a, b)) = (a, b)? cicla (recicla (a, b, c)) = recicla (cicla (a, b, c))?
    • 10.2. Prova por Casos maximo :: Int -> Int -> Int maximo n m |n >= m = n |otherwise = m Assertiva: “Para quaisquer números n e m, maximo n m >= n”?.Para quaisquer números m e n definidos, tem-se: m > n ou n >= m.Então, se n >= m: maximo n m = n. Portanto, maximo n m >= n.Se m > n: maxi n m = m e m > n. Portanto, maximo n m > n.Logo, maximo n m >= n.
    • 10.3. Prova por Indução Matemática 10.3.1. Indução Matemática ◦ Sistemas de Provas -> Especificação Formal ◦ Para provar que uma propriedade P(n) é válida para todo natural n, deve-se: Caso base: Provar P(n), para n = 0. Passo indutivo: Para n > 0, provar P(n), assumindo que P(n-1) é válida. fatorial 0 = 1 -- (fat 1) fatorial n = n * fatorial (n - 1) -- (fat 2) Como provar?
    • 10.3. Prova por Indução MatemáticaPodemos agora provar a seguinte propriedadedos naturais:◦ P(n): fatorial n > 0, para todo natural n.O esquema de prova é feito da seguinte forma:◦ Caso base (P(0)): fatorial 0 = 1 (por fat 1) e 1 > 0. Logo fatorial 0 > 0.◦ Passo indutivo (P(n)): fatorial n = n * fatorial (n-1), (por fat 2) admitindo-se que n>0. A hipótese de indução informa que fatorial (n-1) > 0, ou seja, a propriedade P é válida para n-1.
    • 10.3. Prova por Indução MatemáticaAssim o fatorial de n é o produto de doisfatores sendo ambos maiores que zero, ouseja, temos >0 * >0. O produto de doisnúmeros positivos é também positivo. Logo,maior que 0.Como a propriedade P é válida para o casobase e para o passo indutivo, então ela éválida para todo n natural. Esta última parteé a conclusão da prova.
    • 10.3. Prova por Indução Matemática 10.3.2. Prova por Indução ◦ Enquanto uma indução formula provas para P(0), P(1), ..., a definição recursiva constrói resultados para fatorial 0, fatorial 1, .... ◦ Esta forma de prova normalmente é aplicada à funções definidas por recursão primitiva uma vez que representa tão somente um processo de tradução; ◦ Guia de passos a ser seguido nos esquemas de provas por indução em Haskell [Simon Thompson] Estágio 0: escrever o objeto da prova em linguagem natural, Estágio 1: escrever o objeto da prova em linguagem formal, Estágio 2: escrever os sub-objetos da prova por indução: P(0): P(n), para todo n>0, assumindo P(n-1) Estágio 3: Provar P(0) Estágio 4: Provar P(n), para n>0, lembrando que deve e pode usar P(n-1)
    • 10.3. Prova por Indução Matemática Exemplo: power2 :: Int −> Int power2 0 = 1 (1) power2 r = 2 * power2 (r - 1) (2) sumPowers :: Int − > Int sumPowers 0 = 1 (3) sumPowers r = sumPowers (r-1) + power2 r (4)Provar que sumPowers n + 1 = power2 (n + 1).
    • 10.3. Prova por Indução MatemáticaEstágio 0: provar que a soma das potências de 2 de 0 a n, adicionada a 1 é igual a (n + 1)-ésima potência de 2.Estágio 1: provar P(n): sumPowers n + 1 = power2 (n+1)Estágio 2: sumPowers 0 + 1 = = power2 (0 + 1), para n = 0? sumPowers n + 1 = = power2 (n + 1), para n > 0?, assumindo que sumPowers (n - 1) + 1 = power2 nEstágio 3: sumPowers 0 + 1 = 1 + 1 = 2 –por (3) power2 (0 + 1) = 2 * power2 0 = 2 * 1 = 2 –por (2) logo, a prova é válida para o caso base. sumPowers n + 1 = sumPowers (n-1) + power2 n + 1 –por (4) = sumPowers(n-1) + 1 + power2 n –pela comutatividade de + = power2 n + power2 n –pela hip. de indução = 2 * power2 n = power2 (n+1) –por (2)
    • 10.3. Prova por Indução MatemáticaExercícios:◦ Prove que, para todo número natural n,fac (n + 1) >= power2 n.◦ Prove que, para todo número natural n,fib (n+1) >= power2 (n div 2).
    • Resumo Em Haskell, uma função é uma operação que transforma suas entradas em uma saída. Um tipo é uma coleção de objetos similares. Todo objeto deve ter um tipo claramente definido. As funções definidas em um programa em Haskell podem ser usadas na avaliação de expressões. Tipos de dados primitivos e as tuplas. Exceções e provas.