SlideShare uma empresa Scribd logo
Haskell Seminário de Linguagens de Programação GUILHERME GOMES NEVES DE OLIVEIRA RENZO AUGUSTO LAPELLIGRINI PETRI
ROTEIRO Programação Funcional Histórico Definição Arquitetura Características Aplicações Estrutura Léxica e Sintática Sintaxe HUGS GHC YHC Comparação Curiosidades Conclusão Bibliografia
O que é Haskell ? Haskell  é uma linguagem de programação funcional
Paradigma Funcional É um paradigma de programação que trata a computação como uma avaliação de funções matemáticas; Mapeamento dos valores de entrada nos valores de retorno, através de funções; Um programa funcional é uma única expressão, que é executado através da avaliação da expressão; inputs output  12 34 46
Programação Funcional Um programa funcional é uma função que resolve um problema; Programação funcional é um  “estilo”  de programação, onde a idéia básica é computar argumentos por meio de funções;  Uma linguagem funcional é aquela que  suporta  a abstração dos problemas em funções; Essa função pode envolver funções de várias variáveis e é descrito em uma anotação que obedece a princípios matemáticos; O resultado da função é a solução do problema e está separado da entrada para a função;
Funcional X Imperativo Alto nível de abstração; Programas mais simples; Maior raciocínio sobre programas; sum =0; for(int i = 1; i < 11; i++ ) sum = sum + i; sum [1..10] O método de computação é por:  variable assignment; ESTADO O método de computação é:  function application VALORES
Histórico 1930: Alonzo Church desenvolveu  o cálculo de  lambda , um simples, mas poderoso teorema de funções.
Histórico 1950: John McCarthy desenvolveu  Lisp , a primeira linguagem funcional, com influência da  teoria de lambda  mas  aceitando atribuições de variáveis.
Histórico 1970: Robin Milner e outros desenvolveram a   ML , a primeira linguagem funcional moderna, com introdução de inferência de tipos  e tipos polimórficos.
Histórico 1987:
Histórico Em um encontro internacional, um comitê de pesquisadores iniciaram o  desenvolvimento de   uma linguagem puramente funcional; Houve um forte consenso nessa reunião que o uso mais generalizado dessa classe de linguagens funcionais estava sendo prejudicado pela falta de uma linguagem comum; O início do seu desenvolvimento remonta o ano de 1987, quando, numa conferência realizada em Amsterdã, a comunidade de programação funcional decidiu implementar uma linguagem puramente funcional. Para isso, foi designado um comitê responsável pela implementação do projeto;
O nome  Haskell  é uma homenagem ao pesquisador Haskell Brooks Curry, sendo o responsável pelo desenvolvimento da lógica matemática em que a linguagem se baseia. Histórico
Histórico
2003: O comitê publicou  Haskell 98 , definindo uma versão estável da linguagem. Histórico
Influência Haskell  foi fortemente influenciada por  ML Algol 60 Algol 68 ML Modula Pascal Haskell Lisp
Atualmente
Nova vida ? Usuários 1,000,000 1 100 10,000 1990 1995 2000 2005 2010
Definindo Haskell  é uma linguagem de programação funcional; É um produto de código aberto com mais de vinte anos de pesquisa de ponta, permitindo o desenvolvimento rápido de software; Com um forte apoio para a integração com outras linguagens, construídos em simultaneidade e  paralelismo , possuindo: Depuradores , “ profilers” ,  bibliotecas ricas  e uma comunidade ativa; Haskell  torna mais fácil de produzir software de alta qualidade flexível de manutenção; Haskell  é baseada no cálculo   lambda , portanto, o símbolo, λ, é utilizado como parte do logotipo Haskell;
Classificação Nível Alto Nível; Geração 3ª Geração; Paradigma Funcional;
Arquitetura IDE Haskell (Kernel) Haskell Service (Modules) Interface Link Direto GHC (Compilador)
Kernel Haskell Haskell  adotou a possibilidade de inserções e retiradas das estruturas sintáticas e semânticas do seu núcleo, podendo assim adaptá-la, pois realiza a simples tradução para/dessas construções. Se essas traduções são aplicadas de forma exaustiva, o resultado é um programa escrito em um pequeno subgrupo de Haskell que chamamos de Haskell  kernel ; O  kernel  não é formalmente especificado, ele é essencialmente uma variante do cálculo lambda com uma semântica denotacional simples. A tradução de cada estrutura sintática é introduzido como a sintaxe do kernel; Este projeto modular facilita o raciocínio sobre programas Haskell e fornece orientações úteis para os desenvolvedores da linguagem;
Estrutura sintática e semântica abstrata de Haskell, bem como a forma como se relaciona pode ser dividida em:  Nível 1 -  Conjunto de  módulos : Os módulos oferecem uma maneira para controlar  namespaces ; Nível 2 -  Um módulo é composto de: Uma coleção  de  declarações(definições de  tipos de dados, classes e tipo de informação; Nível 3   -  E xpressões : Uma expressão denota um  valor  e tem um  tipo estático ; Haskell é composto de expressões ; Nível 4   - No nível mais baixo é  a  estrutura léxica: A estrutura lexica capta a representação concreta dos programas Haskell em arquivos de texto; Estrutura do Programa
Estrutura do Programa Análise Legenda: Declarações; Programa; Módulos; Léxico;
Expressão Uma expressão é avaliada como um  valor  e tem um  tipo estático ; Valores  e  tipos  NÃO   são misturados em Haskell; No entanto,  HASKELL  permite: Definir tipos de dados pelo usuário;  Polimorfismo paramétrico;  Sobrecarga  (usando  tipo classes ); Erros em Haskell: Tratados por exceções; Tecnicamente, eles não são distinguíveis  nontermination ; No entanto, o compilador(GHC) provavelmente vai tentar fornecer informações úteis sobre os erros; TIPO VALOR
Namespaces Existem seis tipos de nomes em  Haskell : Os de  variáveis  e  construtores  denotam valores; Tipo de Variáveis ,  Tipo de  construtores  e  Tipo de classes  referem-se a entidades ligadas ao sistema de tipos; Nomes de módulos  referem-se a módulos; Existem duas restrições à nomeação :  Os nomes de variáveis e variáveis de tipo são identificadores que começam com letras minúsculas ou sublinhado;  Os outros quatro tipos de nomes são identificadores que começam com letras maiúsculas; Um identificador não deve ser usado como o nome de um construtor de tipo e uma classe no mesmo escopo;
Características Gerais Concisa: Programas escritos em linguagem funcionais tendem a ser mais concisos do que os seus equivalentes em linguagens imperativas. De uma forma geral a redução em linhas de código pode variar numa razão de 2 a 10; Fácil compreensão; Forte sistema de tipo: Haskell  é fortemente tipada , eliminando uma grande quantidade de erros comuns durante a compilação. De uma forma geral, um sistema de tipo permite que o programador indique à piori como devem ser tratados os dados, associado-os a um tipo. Com um forte sistema de tipos não existe, por exemplo, a possibilidade de tratar um inteiro como um apontador ou seguir um apontador nulo. Avaliação  lazy : Muitas linguagens funcionais só avaliam as partes do programa que são necessárias para o cálculo que é efetuado. Designa-se a este tipo de avaliação por  lazy . As estruturas de dados, como as listas, são avaliadas só até onde for necessário podendo haver partes delas que nem são avaliadas.
Características Gerais Abstração poderosa: As funções de ordem elevada são um mecanismo de abstração que é oferecido pelas linguagens funcionais. Consiste em poder usar funções como argumentos, parâmetros de saída, armazenamento em estruturas de dados e qualquer outra operação que possa ser efetuada com valores de qualquer tipo de dados. A principal vantagem é que a utilização de funções de ordem elevada pode aumentar bastante a estrutura e modularidade de muitos programas. Gestão automática de memória: Muitos programas precisam alocar memória dinamicamente na  heap . Em C utilizam-se funções específicas (malloc) para alocar o espaço e inicializá-lo. O programador é também responsável por liberar a área alocada, caso contrário está sujeito à ocorrência de apontadores vazios. As linguagens funcionais libertam o programador destas tarefas e semelhante ao Java possuem mecanismos de  garbage collector  que se encarregam de assumir toda a gestão de memória de forma automática.
Características Os programas escritos em  Haskel l são geralmente chamados de scripts, por isso a extensão normalmente é “hs” (haskell scripts); Haskell  prioriza o tempo do programador em relação ao da CPU; Módulos permitem um crescimento linear dos projetos com Haskell; Avaliação  lazy   Avaliação com necessidade;
Características Resumindo as características de um programa em Haskell são: Breves e legíveis; Baseiam-se no cálculo lambda; Sem  dump de memória ; Grande reusabilidade de código; Poderosas abstrações;
Características Interpretada e/ou Compilada; Alta portabilidade  Possui versões pra todos os sistemas operacionais mais usados atualmente; GHC:  É o compilador mais usado. É o mais rápido e suporta compilação incremental; HUGS : É o interpretador mais usado.  Outras ferramentas:  YHC , nhc98, HBI, HBC, Helium, dentre outras;
Por que Haskell ? Haskell oferece: Simplificação de tarefas; Menos erros e maior confiabilidade; Um menor  &quot;gap semântico &quot; entre o programador e a linguagem; Haskell é uma linguagem de amplo espectro, apropriado para uma variedade de aplicações.
  É particularmente adequada para programas que precisam ser altamente modificáveis e de fácil manutenção; Grande parte da vida do produto de software é gasto em  especificação ,  projeto  e  manutenção , e não em  programação ; Linguagens funcionais são excelentes para escrever especificações que podem realmente ser executadas (e, portanto testado e depurado); Essa especificação então  é  o primeiro protótipo do programa final; Existe um controle rigoroso de efeitos colaterais eliminando uma enorme classe de interações imprevisíveis; Por que Haskell ?
Aplicações Computação simbólica; Processamento de listas; Aplicações Científicas; Aplicações de IA: Sistemas Especialistas; Representação de conhecimento; Processamento de linguagem natural; Fins acadêmicos; Jogos; Compiladores;
Softwares Fran (animation); A Wiki page; Haskore(music); CGI programming in Haskell; Happy (Parse Generator); Derive  (Automatic derivation of classes from data declarations); Tk Gofer  (The Tk GUI library ported to Go Gofer, linguagem similar ao Haskell);
Quem usa ? Microprocessor verification
Estrutura Léxica e Sintática
Module
Export
Definitions
Declaration Functions
Decls
Expression
Expr
Patroon
Type Typ
Context Classe
Literal Char
Var e outros
Simbols
Árvore de derivação O  parser  é o programa responsável pela análise da estrutura sintática; Hugs  é o  parser  para Haskell; 2  3+4 = 4 + 2  3 2
Sintaxe
Sintaxe Trabalha-se somente com funções, seus parâmetros e seus retornos; É case-sensitive; Não possui comandos de repetição como While e For; Sem limites para identificadores;
Equivalência Matematicamente Haskell f(x) f(x,y) f(g(x)) f(x,g(y)) f(x)g(y) f x f x y f (g x) f x (g y) f x * g y
As regras de escopo em  Haskell  ditam que se uma expressão está na forma apresentada abaixo, o escopo do identificador vi é o mesmo de e, assim como todos do lado direito de todas as definições de  let .  Regra de Escopo let  v1 = e1 v2 = e2  ...  vi = ei ... in e   Escopo de vi: Parte do programa onde vi possui valor = ei
Haskell permite á omissão de “{ }&quot; e &quot;;“  usando regra layout; A regra de Layout entra em vigor quando existe a omissão de chaves antes de : “ where”, “ let” “ do” “ of”.  Regras de Layout
Regras de Layout a = 10 b = 20 c = 30 a = 10 b = 20 c = 30 a = 10 b = 20 c = 30
a = b + c where b = 1 c = 2 d = a * 2 a = b + c where {b = 1; c = 2} d = a * 2 Implícito Explícito Regras de Layout =
O que é um TIPO? Um tipo é um nome para uma  coleção  de valores relacionados (propriedades em comum) Por exemplo, em  Haskell , um tipo básico é:   True Bool False
Tipos em Haskell e :: t Cada expressão bem formado tem um tipo, que é calculada automaticamente em tempo de compilação usando um processo chamado  inferência de tipos . Usamos a notação:   e  ::  T   para indicar que a avaliação da expressão produz um valor do tipo   T .
Tipos Básicos Bool   True, False Char   'a', 'x', '\034', '\n'  String   “oi”, “Sim” Int  0, 94, -45  Float   3.0, 0.54422  Double   3.1415 Bool -  Valores Lógicos Char -  Caracteres simples Integer -  Inteiros de precisão arbitrária Float - Números de ponto flutuante String -  String de caracteres Int -  Inteiros de precisão fixa
Operadores Básicos > maior >= maior ou igual == igual /= diferente < menor <= menor  ou igual +  Soma -  Subtração *  Multiplicação ^ Potência div  Divisão inteira mod  resto da divisão abs  valor absoluto de um inteiro negate  troca o sinal do valor   &&  e   | |  ou not  negação
Tipo Lista Em geral: Uma  lista  é uma sequência de valores do mesmo tipo : [t]  é um tipo de litsta com elementos do tipo  t . [1,2,3,4]  :: [Int] [False,True,False] :: [Bool] [‘a’,’b’,’e’] :: [Char]
Operação com Listas Funções de operações de listas: head [] ghci> head [5,4,3,2,1]   5   tail ghci> tail [5,4,3,2,1]   [4,3,2,1]      last ghci> last [5,4,3,2,1]   1  init ghci> init [5,4,3,2,1]   [5,4,3,2]          Retorna o primeiro elemento da lista. Retorna a calda da lista, ou, não exibe o primeiro elemento. Retorna o último elemento da lista.   Retorna todos os elementos da lista menos o último.
Operação com Listas length ghci> length [5,4,3,2,1]   5     reverse ghci> reverse [5,4,3,2,1]   [1,2,3,4,5]      elem ghci> 4 `elem` [3,4,5,6]   True   ghci> 10 `elem` [3,4,5,6]   False          Retorna o comprimento da lista.   Inverte os elementos da lista. Verifica se um elemento está presente na lista.    
Operação com Listas ghci> [1..20]   [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]    ghci> ['a'..'z']   &quot;abcdefghijklmnopqrstuvwxyz“    ghci> ['K'..'Z']   &quot;KLMNOPQRSTUVWXYZ&quot;               Selecionando intervalo de elementos em listas.    
Tuplas Tuplas  são usadas quando se sabe exatamente quantos elementos desejamos combinar, independente do seu tipo. first ghci> fst (8,11)   8   ghci> fst (&quot;Wow&quot;, False)   &quot;Wow&quot; zip ghci> zip [1,2,3,4,5] [5,5,5,5,5]   [(1,5),(2,5),(3,5),(4,5),(5,5)]   ghci> zip [1 .. 5] [&quot;one&quot;, &quot;two&quot;, &quot;three&quot;, &quot;four&quot;, &quot;five&quot;]   [(1,&quot;one&quot;),(2,&quot;two&quot;),(3,&quot;three&quot;),(4,&quot;four&quot;),(5,&quot;five&quot;)] Recebe um par e retorna o primeiro elemento.     Podem conter combinação de vários tipos .   Utilizado para combinar os elementos de duas listas.
Funções ” x” é o nome da função. Os tipos dos 4 argumentos da função. O último tipo especificado identifica o tipo de dado a ser retornado. As definições de funções em  Haskell  podem ser feitas por meio de uma sequência de equações.  <nome da função ><corpo> x : : Int -> Int -> Float  -> Bool -> Int add :: Int -> Int -> int add x y = x + y
Funções Guards é uma característica na definição de funções, que exploram a capacidade de se inserir condições que são utilizadas como alternativas para a função. guard. A função max retorna o maior valor entre dois números. max : : Int -> Int -> Int max x y  | x >= y  = x  se x >= y então retorne x |  otherwise   = y   caso contrário, retorne y
Criando Funções É possivel criar suas próprias funções: Salvando a função como nome.hs é possível executá-la posteriormente. Função que recebe um número e multiplica ele por dois: doubleMe x = x + x ghci> nome:   [1  de  1] Compilando principal              (nome.hs, interpretado)   Ok, módulos carregados: Main.   ghci> doubleMe 9   18   ghci> doubleMe 8,3   16,6  A mesma pode ser utilizada com números de qualquer tipo.
Criando Funções É possível também chamar funções dentro de funções.   doubleUs y = x *2 + y *2 ghci> doubleUs 4 9   26   ghci> doubleUs 2,3 34,2   73,0   ghci> doubleUs 28 88 + doubleMe 123   478   Sendo assim é possível redefinir uma função. doubleUs x y = doubleMe x + y doubleMe  
Polimorfismo Há polimorfismo universal, a função possui um tipo genérico e a mesma definição é usada para vários tipos.  A função  length  pode retornar tanto o tamanho de uma String, quanto de uma Lista. Basta declarar e definir as funções com o mesmo nome, porém com os argumentos próprios para cada objetivo: length : : String -> Int  length : : [a] -> Int
Classes A definição de uma classe consiste em:   class <nome_da_classe> <tipo_de_entrada> where   <assinatura da classe> Exemplo: Class V a where toString a : : a -> String  size  a : : a -> Int Haskell permite que o usuário, programador, crie alguns outros tipos denominados Classes, que funcionam como tipos de dados abstratos. O usuário tem total liberdade para definir inúmeros tipos de classes diferentes. A assinatura da classe define as funções que poderão ser aplicadas aquela classe. ” a” é uma variável que representa qualquer tipo de dado. “ V” é o nome da classe.
Verificação de Tipos Tanto os compiladores quanto os interpretadores Haskell implementam o mecanismo de  checagem forte de tipos de dados , devido a tamanha variedade de tipos.  Monomórfico Polimórfico
Verificação de Tipos- Monomórficos f : : s -> t, onde a função f deve ser aplicada sobre um argumento de tipo s e resultar numa expressão do tipo t. A checagem de tipos monomórficos, isto é, sem polimorfismo.  ” e” é uma expressão que pode ser um literal, uma variável ou constante, ou pode ser construído aplicando uma função sobre seus argumentos, que são cada um também expressões.
Verificação de Tipos- Monomórficos A verificação das expressões naturalmente acaba assumindo uma característica recursiva; O analisador de expressões do compilador/interpretador deve descobrir o que pode ser uma expressão em Haskell e expandir numa árvore até que se obtenha a mais simples declaração dos tipos.  Com esta informação, basta aplicar as regras que estão descritas na definição da própria função e compará-las com os tipos de dados  informados na expressão raiz. Deve-se considerar os quesitos: -  o valor ei retornado deve ser do tipo t; - p padrão de argumentos pj deve ser consistente com os tipos ti indicados na assinatura da função;
Verificação de Tipos-  Polimórficos Para realizar a verificação de tipos em funções polimórficas, o Haskell lança mão do conceito de  unificação . Assim como em linguagens lógicas, uma unificação ocorre quando o analisador de expressões do compilador/interpretador consegue determinar quais variáveis assumirão um determinado argumento genérico, e também de qual tipo dedado será este argumento.
Verificação de Tipos-  Polimórficos A função soma recebe dois argumentos que podem ser de tipos quaisquer, temos nos exemplos a chamada da função com tipos de dados inteiros e também com tipos de ponto flutuante.  Realizar a unificação sobre esta função significa que, ao chamar soma, o primeiro argumento &quot;fecha&quot; com a, o segundo com b e o resultado com c.  Isto permite descobrir como posicionar os argumentos para uma função polimórfica. Agora vejamos um caso mais complexo. Considere a função f abaixo: f : : (a -> b) -> [a] -> [b] Ao chamar f com parâmetros Char -> Int, a unifica com Char e b com Int. Isto vale para toda a expressão, assim teremos:   f : : (Char -> Int) -> [Char] -> [Int]  Note como o Haskell avalia expressões polimórficas, e também o custo adicionado para realizar o processo de unificação.
Exemplos
Main
Declaração Os símbolos “—” “{-  -}” comentários. Declara uma nova função, especificando seu tipo. O símbolo :: pode ser lido como “é do tipo...&quot; Determina que valor tem o valor 35. Determina que square é uma função de Int para Int . Equação que define a função. Define o resultado, x*x , da aplicação de square sobre x (argumento). Nomes de funções começam com letras minúsculas. Nomes de tipos começam com letras maiúsculas. 1   {----------------------------} 2   --  example.hs 3   ---------------------------- 4   valor :: Int 5   valor = 35 6   7   square :: Int -> Int 8   square x = x * x 9
Condição Equação condicional, Os símbolo “|” , “=“ são utilizados para emular o comando de seleção. O valor à direita de “=“ é retornado se a condição for verdadeira. Determina que mystery é um função que recebe 3 Objetos Int  e retorna True ou False  Determina que maxx é uma função que recebe 2 objetos Int e retorna Int . 1   {---------------------------- 2   --  example.hs ----------------------------} 4  mystery :: Int -> Int -> Int -> Bool 5  mystery a b c = (a==b) && (b==c) 6 7  maxx :: Int -> Int -> Int 8  maxx m n 9   | m >= n = m 10   | otherwise = n
Cálculos Como cálculos são efetuados em Haskell? A comparação é feita com os valores de a e b, depois b com c  o resultado é a comparação da 1 ˚   sentença com a segunda. mystery a b c = (a == b)  &&  (b == c) mystery 5 8 8 = (5==8)  &&  (8==8) =  False   &&   True =  False mystery 9 9 9 = (9==9)  &&  (9 == 9) =  True   &&   True =  True
Exemplo envolvendo equação condicional: Cálculos maxx m n | m >= n  = m |  otherwise  = n maxx 7 4 = 7 >= 4 =  True = 7 maxx 12 45 = 12 >= 45 =  False =  otherwise  =  True = 45
Quick Sort  em Haskell Se a lista é vazia, não há nada a ordenar . s é o 1 o  elemento da lista que é utilizado com pivo. xs representa o restante da lista. A lista restante é dividida em 2 partes: a primeira contém apenas os elementos de xs que são menores ou igual a s. A segunda, contém apenas os elementos de xs que são maiores. As duas listas são ordenadas recursivamente e o resultado é obtido concatenando a primeira lista (ordenada), com a lista que contém s e a segunda lista (ordenada.) qsort [] = [] qsort ( s : xs ) = qsort [ x | x  <-  xs , x < s]  ++ [s] ++  qsort [ x|x <- xs, x >= s  ]
Interação Para escrever programas interativos que leem dados a partir do teclado e escrevem na tela, são necessários:  IO Programas interativos podem ser escritos em Haskell usando tipos que podem envolver efeitos colaterais -  IO . interactive program inputs outputs keyboard screen
HUGS HUGS Interpretador; Escrito em C; Portável; Leve; Ideal para iniciantes;
GHC GHC Interpretador e Compilador; Escrito em Haskell; Menos portável; Mais lento; Exige mais memória; Produz programas mais rápidos;
O Compilador: GHC O compilador em si é escrito inteiramente em Haskell. Estrutura Geral Diagrama de blocos da sua estrutura de alto nível GHC  é empacotado como um binário único;  GHC  é compilado, sem o seu  front-ends , como uma  biblioteca; Pode ser importado por qualquer  front-ends   de programas Haskell.
O Compilador: GHC HscMain: Lida com a compilação de um único módulo; Gerente de compilação:   Gerencia a compilação de vários módulos; Ela possui uma interface chamada de  API GHC ;  GHCi: Ambiente interativo, é implementado no  compilador / ghci / InteractiveUI.hs  ; Make: É um cliente da API do GHC, e é executada em  compilador / main / Main.hs ; M: Gerador de dependência  Makefile , também é cliente da API do GHC, e é implementado no  compilador / main / DriverMkDepend.hs ; &quot;one-shot mode“ : Onde o GHC compila cada arquivo na linha de comando em separado (por exemplo , Foo.hs c GHC);   Este modo ignora a API do GHC;
O GHC API Coordenam a compilação de vários módulos; API GHC  suporta apenas um cliente que é na verdade a execução do código; A sequência típica da  API do GHC  é algo como o seguinte: Criar uma nova sessão:  newSession; Definir os flags:  getSessionDynFlags, setSessionDynFlags; Adicione algumas  tags :  setTargets, addTarget, guessTarget; Realizar  Análise de dependência :  depanal; Load (compile) os arquivos de origem:  load ;
Sequência Tags As  tags  especificam a localização da fonte de arquivos ou módulos no topo da árvore de dependência; Análise de dependência A fase de análise de dependência determina todos os arquivos fonte Haskell que vão ser compilados ou carregados na sessão atual, percorrendo as dependências transitivas das  tags .   Este processo é chamado de  downsweep  porque estamos atravessando a árvore de dependência das metas; Carregando (compilação) dos Módulos Quando a análise de dependência é completa, os módulos são carregados chamando  load ; Finalmente, todo os  objetcs codes  são carregados junto com os byte-code, todos juntos na memória;  Chama-se o  linker   Link externo para gerar o código objeto em um binário;
Tipos de dados-chave A chave para a compreensão do GHC é compreender os seus tipos de dados-chave.
GHC : O Code Generator Storage Manager; Generated Cmm Naming Convention; Modules; Memory and Register Management; Function Calls and Parameter Passing ; Special runtime support ;
GHC : Storage Manager
GHC: A disposição dos objetos Heap Todos os objetos têm uma pilha de layout básico;   O diagrama abaixo mostra o layout de um objeto de  heap : Um objeto de  heap  sempre começa com um  cabeçalho ; O cabeçalho é o  ponteiro de informações , que aponta para a tabela de informação; O compilador precisa saber o layout de objetos de heap, essa informação é passada para o compilador em tempo de execução
Tabelas Info A  tabela info  contém todas as informações do estado atual no tempo de execução:
Tabelas Info closure type É uma constante que descreve o tipo de fechamento (de função, de conversão, o construtor, etc.) ; SRT bitmap Campo é utilizado para apoiar o  Garbage Collection ; Layout: Campo descreve o layout da carga para o  Memory Manager ;
Tabelas Info Alguns tipos de objeto adicionam mais campos ao final da tabela de informações, nome das funções, endereços de retorno; Note que a tabela de informação é imediatamente seguido pelo código de entrada. Isto reduz o tamanho da tabela de informações e elimina uma ponteiro indireto para o código de entrada;
Objetos Dinâmicos X Estáticos Objetos caem em duas categorias: Dinâmica  : Objetos residem no  heap , e pode ser movido pelo coletor de lixo; Objetos dinâmicos têm um tamanho mínimo, pois cada objeto deve ser grande o suficiente para ser substituído por um ponteiro de encaminhamento ( Forwarding pointers ) durante a GC; Estático: Objetos residem no código objeto compilado; Eles nunca são movidos, porque os ponteiros para objetos estão espalhadas através do código objeto; Objetos estáticos têm um campo adicional, chamado de  campo link estático . O campo de link estático é usado pela GC link para todos os objetos estáticos em uma lista, e assim que ele pode dizer se ela tem visitado um determinado objeto estático ou não;  Para saber se um determinado objeto é estático ou dinâmico, usa-se a macro  HEAP_ALLOCED ()  ;
Layout da pilha Cada objeto  TSO  contém uma pilha; A pilha de um  TSO  cresce para baixo;  A pilha consiste de uma sequência de  quadros de pilha  (às vezes também chamados  registros de ativação ), onde cada quadro tem o mesmo layout como um objeto de heap: Objeto  TSO  é: uma Thread do estado do objeto;   Ele representa o estado completo de um segmento, incluindo a sua stack;
Layout da pilha O  SRT   = Campo de ponteiro para a tabela de referência estático (SRT);
Garbage Collection O  GC  é projetado para ser flexível, suportando muitas maneiras de ajustar o seu comportamento; GC  Geracional, com um número selecionável de gerações em tempo de execução: (G + RTS-<n>-RTS, onde n> = 1). Atualmente ele é um colecionador de gerações tradicional, onde cada coleta recolhe uma determinada geração e as gerações mais jovens. A pilha cresce em armazenamento de um   alocador de blocos ;
Alocador de Blocos O  alocador de blocos  é o responsável por prover a flexibilidade do GC; É o gestor de armazenamento; Ao invés de manter a nossa pilha em uma única região contígua de memória, ou uma região contígua por geração, conseguimos listas ligadas de blocos de memória; Gerenciar regiões contíguas é difícil, especialmente quando você quiser mudar o tamanho de algumas áreas. Um arranjo de armazenamento de bloco-estruturada tem várias vantagens: Redimensionamento áreas de memória é fácil: basta mais blocos para a lista; Gerenciamento de objetos grandes, sem copiar é fácil: atribuir a cada uma um bloco completo, e usar o bloco de ligação para a cadeia juntos; Memória livre pode ser reciclado mais rapidamente, porque é um bloco de um bloco; O conceito baseia-se na propriedade que a maioria dos objetos de dados são significativamente menores que um bloco, e só raramente precisamos alocar objetos que se aproximam ou excedem o tamanho de um bloco.
Alocador de Blocos Estrutura de blocos Cada bloco possui um:  bloco descritor , que contém informações sobre o bloco: o seu campo de ligação, que a geração a que pertence, e assim por diante. Isso é semelhante ao conhecido técnica &quot;BiBOP&quot; (Big Bag de paginação), onde os objetos com marcas semelhantes são reunidos em uma página de modo a evitar a necessidade de armazenar uma etiqueta individual com cada objeto. Megablocks de 1Mb de tamanho (m = 20) com blocos de 4k de tamanho (k = 12)
Garbage Collection A política de coleta de pilha é runtime-ajustável: Você pode selecionar o tamanho de uma geração começa antes que ele seja coletado por meio doRTS + F-<n>-RTS opção, onde <n> é um fator de geração, o tamanho da última vez que foi coletada. O valor padrão é 2, que é uma geração é permitido dobrar de tamanho, antes de serem recolhidos; O GC é uma única thread:   Quando o RTS detecta a pressão de memória GC para todos os tópicos Haskell e um segmento que faz a coleta de lixo e, em seguida, reinicia todos os outros segmentos suspenso; Gerações O GC GHC é um colecionador de gerações. O número de gerações é definido como 2 por padrão e que são referidos como gen 0 e gen 1. gen 0 tem novos objetos, objetos que sobrevivem a coletas de Gen 0 são promovidos a um gen. Objetos antigos residir no gen 1.
Garbage Collection - Estruturas Blocos e blocos Mega O GC aloca memória do sistema operacional em pedaços 1 Mb de tamanho, megablocos, que então se divide em. Cada página 4k é chamado de bloco e está associada a um bloco descripter(BD) . O BD mantém informações sobre um bloco;
Garbage Collection - Estruturas Passos Gerações GHC são divididos em etapas; A última geração, o mais velho tem apenas um passo; A coleta de lixo acontece ao nível das gerações; Então, quando você diz que está coletando gen 0, que é recolher todas as etapas de geração 0. Se você está coletando gen 4, então você está coletando todas as etapas de geração de 0 a gen 4.  Objetos que sobrevivem a uma coleta são promovidos ao escalão imediatamente superior;
Garbage Collection - Estruturas
Garbage Collection - Estruturas
Espaço das Classes Normal Overlap Closed Local Normal Global Implicit Parameters Haskell GHC Methods Dependência local
 
Fluxograma Coerção
Escrito em C; YHC
verification : bytecode :: typechecking : source code YHC
YHC
DICAS Ao definir uma nova função em Haskell, é útil começar por escrever o seu tipo; Dentro de um script, é boa prática para indicar o tipo de cada nova função definida; Ao afirmar os tipos de funções polimórficas que usam números, como a igualdade ou ordenações, tome o cuidado ao incluir as restrições de classe;
Avaliação Alta Flexibilidade : De acordo com a Tese de Church, todo e qualquer  problema resolvido imperativamente possui uma resolução indutiva; Tipagem :  Haskell é extremamente  tipada , sendo conhecido como calculadora funcional.Expressões são reduzidas tendo por base o cálculo lambda. Portabilidade : Interpretadores ou compiladores trabalham em diversos tipos de arquitetura e sistemas operacionais.
Haskell X Outras Linguagens Haskell separa a definição de um tipo a partir da definição dos métodos associados a esse tipo; Uma classe em C++ ou Java normalmente definem a estrutura de dados (variáveis, membro) e as funções associadas com a estrutura (os métodos). Em Haskell, essas definições são separados; As classe definidas por Haskell correspondem às funções virtuais em uma classe C++ e similares a uma interface Java;  Cada instância de uma classe fornece a sua própria definição de cada método, os padrões de classe correspondem às definições padrão para uma função virtual na classe base; Como uma declaração de interface, uma declaração de classe Haskell define um protocolo para a utilização de um objeto em vez de definir um objeto em si;
Haskell X Outras Linguagens C++ e Java anexam as informações de identificação (como um vtable) para a representação de tempo de execução de um objeto. Em Haskell, essa informação está ligado, logicamente, em vez de física para valores, através do tipo de sistema; Não há controle de acesso (tais como público ou privado, de classe componentes) incorporados ao sistema de classe Haskell. Em vez disso, o módulo do sistema deve ser usado para esconder ou revelar os componentes de uma classe.
Comparação
Curiosidades Vídeos: http://www.youtube.com/watch?v=X4-212uMgy8 http://www.youtube.com/watch?v=A1wtQ_mYHHo&feature=related
Curiosidades GHC 6.10.4  Compilador de Haskell; GHCi 6.10.4  O interpretador de  bytecode  e um ambiente interativo para Haskell; Um depurador interativo para Haskell;
Curiosidades Tratamento para Computação paralela:
Curiosidades
Vantagens Suporte à  simultaneidade  e  paralelismo ; Apoiado por uma grande biblioteca de módulos de pacotes; Fornecido com  depuradores e profilers ; Livremente disponível  (código-fonte aberto, pacote de desenvolvimento completo);
Vantagens Fortemente Tipada e Estática; Avaliação Lazy; Polimorfismo Universal Paramétrico; Função (superior e parcial); Ausência de desvios incondicionais;
Desvantagens Requer muita memória; Execução lenta;
Conclusão Neste seminário tivemos a oportunidade de explanar os principais aspectos de implementação da linguagem funcional Haskell.  Além disso também foi discutido aspectos de programação do ponto de vista do usuário da linguagem.  Em geral as linguagens funcionais assumem um papel extremamente específico em projetos de desenvolvimento de software, na maioria dos casos, aplicações com fins especiais conseguem tirar proveito do poder do paradigma funcional. O  Haskell  é funcional mas futuramente estenderá a aplicação suportando vários paradigmas na mesma linguagem, podendo-se programar de forma funcional, imperativa ou orientada a objetos. Naturalmente este suporte sempre possui uma base funcional e através dela se obtém uma abstração de outros paradigmas, porém é fácil notar toda a força do  Haskell  que dá ao programador uma série de recursos de forma extremamente simples e principalmente didática, Possibilita que a linguagem seja facilmente utilizada tanto no âmbito do ensino de programação em linguagens funcionais, como na criação de grandes projetos de aplicativos comerciais mais complexos.  Haskell  nos dá todo o poder do paradigma funcional com a facilidade de implementação e clareza de código.
Bibliografia The Haskell Home Page: www.haskell.org Haskell Reference:  www.zvon.org/other/haskell/Outputglobal Haskell GHC: http://hackage.haskell.org/trac/ghc/wiki/
Dúvidas

Mais conteúdo relacionado

PDF
Haskell
PDF
Aula I - Excel
PDF
Exercício resolvido normalização
PPTX
Aula 1 Excel básico
PDF
Análise de dados com Python para iniciantes
PDF
Aula 5 - Estruturas de seleção simples e composta - parte 1
PDF
Tipos e valores
PDF
Linguagem de programação haskell
Haskell
Aula I - Excel
Exercício resolvido normalização
Aula 1 Excel básico
Análise de dados com Python para iniciantes
Aula 5 - Estruturas de seleção simples e composta - parte 1
Tipos e valores
Linguagem de programação haskell

Semelhante a Seminario haskell (20)

DOCX
P funcional
ODP
Paradigma funcional
PDF
Paradigma Funcional - Caso de Estudo Haskell
PDF
Minicurso - funcional (CTI/2019)
PDF
Haskell aula1 apresentação
PPTX
5 paradigma funcional usando haskell
PDF
Haskell motivaçãoaula2
PDF
Haskell motivação
PDF
Programação funcional
PPTX
PDF
01-Paradigmas.pdf
PDF
TDC2017 | São Paulo - Trilha Programação Funcional How we figured out we had ...
PDF
Programação funcional com_haskell
PDF
Introdução Programação Funcional
PDF
PDF
Haskell - Introdução
PPTX
Linguagem da programação
PPTX
Linguagem da programação
PPTX
Linguágens de programação
POTX
LP003 - AULA 2.potx
P funcional
Paradigma funcional
Paradigma Funcional - Caso de Estudo Haskell
Minicurso - funcional (CTI/2019)
Haskell aula1 apresentação
5 paradigma funcional usando haskell
Haskell motivaçãoaula2
Haskell motivação
Programação funcional
01-Paradigmas.pdf
TDC2017 | São Paulo - Trilha Programação Funcional How we figured out we had ...
Programação funcional com_haskell
Introdução Programação Funcional
Haskell - Introdução
Linguagem da programação
Linguagem da programação
Linguágens de programação
LP003 - AULA 2.potx
Anúncio

Último (11)

PPTX
Informática Aplicada Informática Aplicada Plano de Ensino - estudo de caso NR...
PPTX
Utilizando code blockes por andre backes
PDF
Termos utilizados na designação de relação entre pessoa e uma obra.pdf
PPTX
Arquitetura de computadores - Memórias Secundárias
PPTX
Mecânico de Manutenção de Equipamentos.pptx
PPTX
Como-se-implementa-um-softwareeeeeeeeeeeeeeeeeeeeeeeee.pptx
PDF
eBook - GUIA DE CONSULTA RAPIDA EM ROTEADORES E SWITCHES CISCO - VOL I.pdf
PPTX
Eng. Software - pontos essenciais para o início
PPTX
Gestao-de-Bugs-em-Software-Introducao.pptxxxxxxxx
PPTX
Viasol Energia Solar -Soluções para geração e economia de energia
PDF
Manejo integrado de pragas na cultura do algodão
Informática Aplicada Informática Aplicada Plano de Ensino - estudo de caso NR...
Utilizando code blockes por andre backes
Termos utilizados na designação de relação entre pessoa e uma obra.pdf
Arquitetura de computadores - Memórias Secundárias
Mecânico de Manutenção de Equipamentos.pptx
Como-se-implementa-um-softwareeeeeeeeeeeeeeeeeeeeeeeee.pptx
eBook - GUIA DE CONSULTA RAPIDA EM ROTEADORES E SWITCHES CISCO - VOL I.pdf
Eng. Software - pontos essenciais para o início
Gestao-de-Bugs-em-Software-Introducao.pptxxxxxxxx
Viasol Energia Solar -Soluções para geração e economia de energia
Manejo integrado de pragas na cultura do algodão
Anúncio

Seminario haskell

  • 1. Haskell Seminário de Linguagens de Programação GUILHERME GOMES NEVES DE OLIVEIRA RENZO AUGUSTO LAPELLIGRINI PETRI
  • 2. ROTEIRO Programação Funcional Histórico Definição Arquitetura Características Aplicações Estrutura Léxica e Sintática Sintaxe HUGS GHC YHC Comparação Curiosidades Conclusão Bibliografia
  • 3. O que é Haskell ? Haskell é uma linguagem de programação funcional
  • 4. Paradigma Funcional É um paradigma de programação que trata a computação como uma avaliação de funções matemáticas; Mapeamento dos valores de entrada nos valores de retorno, através de funções; Um programa funcional é uma única expressão, que é executado através da avaliação da expressão; inputs output  12 34 46
  • 5. Programação Funcional Um programa funcional é uma função que resolve um problema; Programação funcional é um “estilo” de programação, onde a idéia básica é computar argumentos por meio de funções; Uma linguagem funcional é aquela que suporta a abstração dos problemas em funções; Essa função pode envolver funções de várias variáveis e é descrito em uma anotação que obedece a princípios matemáticos; O resultado da função é a solução do problema e está separado da entrada para a função;
  • 6. Funcional X Imperativo Alto nível de abstração; Programas mais simples; Maior raciocínio sobre programas; sum =0; for(int i = 1; i < 11; i++ ) sum = sum + i; sum [1..10] O método de computação é por: variable assignment; ESTADO O método de computação é: function application VALORES
  • 7. Histórico 1930: Alonzo Church desenvolveu o cálculo de lambda , um simples, mas poderoso teorema de funções.
  • 8. Histórico 1950: John McCarthy desenvolveu Lisp , a primeira linguagem funcional, com influência da teoria de lambda mas aceitando atribuições de variáveis.
  • 9. Histórico 1970: Robin Milner e outros desenvolveram a ML , a primeira linguagem funcional moderna, com introdução de inferência de tipos e tipos polimórficos.
  • 11. Histórico Em um encontro internacional, um comitê de pesquisadores iniciaram o desenvolvimento de uma linguagem puramente funcional; Houve um forte consenso nessa reunião que o uso mais generalizado dessa classe de linguagens funcionais estava sendo prejudicado pela falta de uma linguagem comum; O início do seu desenvolvimento remonta o ano de 1987, quando, numa conferência realizada em Amsterdã, a comunidade de programação funcional decidiu implementar uma linguagem puramente funcional. Para isso, foi designado um comitê responsável pela implementação do projeto;
  • 12. O nome Haskell é uma homenagem ao pesquisador Haskell Brooks Curry, sendo o responsável pelo desenvolvimento da lógica matemática em que a linguagem se baseia. Histórico
  • 14. 2003: O comitê publicou Haskell 98 , definindo uma versão estável da linguagem. Histórico
  • 15. Influência Haskell foi fortemente influenciada por ML Algol 60 Algol 68 ML Modula Pascal Haskell Lisp
  • 17. Nova vida ? Usuários 1,000,000 1 100 10,000 1990 1995 2000 2005 2010
  • 18. Definindo Haskell é uma linguagem de programação funcional; É um produto de código aberto com mais de vinte anos de pesquisa de ponta, permitindo o desenvolvimento rápido de software; Com um forte apoio para a integração com outras linguagens, construídos em simultaneidade e paralelismo , possuindo: Depuradores , “ profilers” ,  bibliotecas ricas e uma comunidade ativa; Haskell torna mais fácil de produzir software de alta qualidade flexível de manutenção; Haskell é baseada no cálculo lambda , portanto, o símbolo, λ, é utilizado como parte do logotipo Haskell;
  • 19. Classificação Nível Alto Nível; Geração 3ª Geração; Paradigma Funcional;
  • 20. Arquitetura IDE Haskell (Kernel) Haskell Service (Modules) Interface Link Direto GHC (Compilador)
  • 21. Kernel Haskell Haskell adotou a possibilidade de inserções e retiradas das estruturas sintáticas e semânticas do seu núcleo, podendo assim adaptá-la, pois realiza a simples tradução para/dessas construções. Se essas traduções são aplicadas de forma exaustiva, o resultado é um programa escrito em um pequeno subgrupo de Haskell que chamamos de Haskell  kernel ; O kernel não é formalmente especificado, ele é essencialmente uma variante do cálculo lambda com uma semântica denotacional simples. A tradução de cada estrutura sintática é introduzido como a sintaxe do kernel; Este projeto modular facilita o raciocínio sobre programas Haskell e fornece orientações úteis para os desenvolvedores da linguagem;
  • 22. Estrutura sintática e semântica abstrata de Haskell, bem como a forma como se relaciona pode ser dividida em: Nível 1 - Conjunto de  módulos : Os módulos oferecem uma maneira para controlar namespaces ; Nível 2 - Um módulo é composto de: Uma coleção de  declarações(definições de tipos de dados, classes e tipo de informação; Nível 3 - E xpressões : Uma expressão denota um  valor  e tem um  tipo estático ; Haskell é composto de expressões ; Nível 4 - No nível mais baixo é a  estrutura léxica: A estrutura lexica capta a representação concreta dos programas Haskell em arquivos de texto; Estrutura do Programa
  • 23. Estrutura do Programa Análise Legenda: Declarações; Programa; Módulos; Léxico;
  • 24. Expressão Uma expressão é avaliada como um  valor  e tem um tipo estático ; Valores e tipos NÃO são misturados em Haskell; No entanto, HASKELL permite: Definir tipos de dados pelo usuário; Polimorfismo paramétrico; Sobrecarga  (usando  tipo classes ); Erros em Haskell: Tratados por exceções; Tecnicamente, eles não são distinguíveis nontermination ; No entanto, o compilador(GHC) provavelmente vai tentar fornecer informações úteis sobre os erros; TIPO VALOR
  • 25. Namespaces Existem seis tipos de nomes em Haskell : Os de  variáveis  e  construtores  denotam valores; Tipo de Variáveis ,  Tipo de construtores e  Tipo de classes referem-se a entidades ligadas ao sistema de tipos; Nomes de módulos  referem-se a módulos; Existem duas restrições à nomeação : Os nomes de variáveis e variáveis de tipo são identificadores que começam com letras minúsculas ou sublinhado; Os outros quatro tipos de nomes são identificadores que começam com letras maiúsculas; Um identificador não deve ser usado como o nome de um construtor de tipo e uma classe no mesmo escopo;
  • 26. Características Gerais Concisa: Programas escritos em linguagem funcionais tendem a ser mais concisos do que os seus equivalentes em linguagens imperativas. De uma forma geral a redução em linhas de código pode variar numa razão de 2 a 10; Fácil compreensão; Forte sistema de tipo: Haskell é fortemente tipada , eliminando uma grande quantidade de erros comuns durante a compilação. De uma forma geral, um sistema de tipo permite que o programador indique à piori como devem ser tratados os dados, associado-os a um tipo. Com um forte sistema de tipos não existe, por exemplo, a possibilidade de tratar um inteiro como um apontador ou seguir um apontador nulo. Avaliação lazy : Muitas linguagens funcionais só avaliam as partes do programa que são necessárias para o cálculo que é efetuado. Designa-se a este tipo de avaliação por lazy . As estruturas de dados, como as listas, são avaliadas só até onde for necessário podendo haver partes delas que nem são avaliadas.
  • 27. Características Gerais Abstração poderosa: As funções de ordem elevada são um mecanismo de abstração que é oferecido pelas linguagens funcionais. Consiste em poder usar funções como argumentos, parâmetros de saída, armazenamento em estruturas de dados e qualquer outra operação que possa ser efetuada com valores de qualquer tipo de dados. A principal vantagem é que a utilização de funções de ordem elevada pode aumentar bastante a estrutura e modularidade de muitos programas. Gestão automática de memória: Muitos programas precisam alocar memória dinamicamente na heap . Em C utilizam-se funções específicas (malloc) para alocar o espaço e inicializá-lo. O programador é também responsável por liberar a área alocada, caso contrário está sujeito à ocorrência de apontadores vazios. As linguagens funcionais libertam o programador destas tarefas e semelhante ao Java possuem mecanismos de garbage collector que se encarregam de assumir toda a gestão de memória de forma automática.
  • 28. Características Os programas escritos em Haskel l são geralmente chamados de scripts, por isso a extensão normalmente é “hs” (haskell scripts); Haskell prioriza o tempo do programador em relação ao da CPU; Módulos permitem um crescimento linear dos projetos com Haskell; Avaliação lazy Avaliação com necessidade;
  • 29. Características Resumindo as características de um programa em Haskell são: Breves e legíveis; Baseiam-se no cálculo lambda; Sem dump de memória ; Grande reusabilidade de código; Poderosas abstrações;
  • 30. Características Interpretada e/ou Compilada; Alta portabilidade Possui versões pra todos os sistemas operacionais mais usados atualmente; GHC: É o compilador mais usado. É o mais rápido e suporta compilação incremental; HUGS : É o interpretador mais usado. Outras ferramentas: YHC , nhc98, HBI, HBC, Helium, dentre outras;
  • 31. Por que Haskell ? Haskell oferece: Simplificação de tarefas; Menos erros e maior confiabilidade; Um menor &quot;gap semântico &quot; entre o programador e a linguagem; Haskell é uma linguagem de amplo espectro, apropriado para uma variedade de aplicações.
  • 32.   É particularmente adequada para programas que precisam ser altamente modificáveis e de fácil manutenção; Grande parte da vida do produto de software é gasto em  especificação ,  projeto  e  manutenção , e não em  programação ; Linguagens funcionais são excelentes para escrever especificações que podem realmente ser executadas (e, portanto testado e depurado); Essa especificação então  é  o primeiro protótipo do programa final; Existe um controle rigoroso de efeitos colaterais eliminando uma enorme classe de interações imprevisíveis; Por que Haskell ?
  • 33. Aplicações Computação simbólica; Processamento de listas; Aplicações Científicas; Aplicações de IA: Sistemas Especialistas; Representação de conhecimento; Processamento de linguagem natural; Fins acadêmicos; Jogos; Compiladores;
  • 34. Softwares Fran (animation); A Wiki page; Haskore(music); CGI programming in Haskell; Happy (Parse Generator); Derive (Automatic derivation of classes from data declarations); Tk Gofer (The Tk GUI library ported to Go Gofer, linguagem similar ao Haskell);
  • 35. Quem usa ? Microprocessor verification
  • 36. Estrutura Léxica e Sintática
  • 41. Decls
  • 43. Expr
  • 50. Árvore de derivação O parser é o programa responsável pela análise da estrutura sintática; Hugs é o parser para Haskell; 2  3+4 = 4 + 2  3 2
  • 52. Sintaxe Trabalha-se somente com funções, seus parâmetros e seus retornos; É case-sensitive; Não possui comandos de repetição como While e For; Sem limites para identificadores;
  • 53. Equivalência Matematicamente Haskell f(x) f(x,y) f(g(x)) f(x,g(y)) f(x)g(y) f x f x y f (g x) f x (g y) f x * g y
  • 54. As regras de escopo em Haskell ditam que se uma expressão está na forma apresentada abaixo, o escopo do identificador vi é o mesmo de e, assim como todos do lado direito de todas as definições de let . Regra de Escopo let v1 = e1 v2 = e2 ... vi = ei ... in e Escopo de vi: Parte do programa onde vi possui valor = ei
  • 55. Haskell permite á omissão de “{ }&quot; e &quot;;“ usando regra layout; A regra de Layout entra em vigor quando existe a omissão de chaves antes de : “ where”, “ let” “ do” “ of”. Regras de Layout
  • 56. Regras de Layout a = 10 b = 20 c = 30 a = 10 b = 20 c = 30 a = 10 b = 20 c = 30
  • 57. a = b + c where b = 1 c = 2 d = a * 2 a = b + c where {b = 1; c = 2} d = a * 2 Implícito Explícito Regras de Layout =
  • 58. O que é um TIPO? Um tipo é um nome para uma coleção de valores relacionados (propriedades em comum) Por exemplo, em Haskell , um tipo básico é: True Bool False
  • 59. Tipos em Haskell e :: t Cada expressão bem formado tem um tipo, que é calculada automaticamente em tempo de compilação usando um processo chamado inferência de tipos . Usamos a notação: e :: T para indicar que a avaliação da expressão produz um valor do tipo T .
  • 60. Tipos Básicos Bool True, False Char 'a', 'x', '\034', '\n' String “oi”, “Sim” Int 0, 94, -45 Float 3.0, 0.54422 Double 3.1415 Bool - Valores Lógicos Char - Caracteres simples Integer - Inteiros de precisão arbitrária Float - Números de ponto flutuante String - String de caracteres Int - Inteiros de precisão fixa
  • 61. Operadores Básicos > maior >= maior ou igual == igual /= diferente < menor <= menor ou igual + Soma - Subtração * Multiplicação ^ Potência div Divisão inteira mod resto da divisão abs valor absoluto de um inteiro negate troca o sinal do valor && e | | ou not negação
  • 62. Tipo Lista Em geral: Uma lista é uma sequência de valores do mesmo tipo : [t] é um tipo de litsta com elementos do tipo t . [1,2,3,4] :: [Int] [False,True,False] :: [Bool] [‘a’,’b’,’e’] :: [Char]
  • 63. Operação com Listas Funções de operações de listas: head [] ghci> head [5,4,3,2,1]   5   tail ghci> tail [5,4,3,2,1]   [4,3,2,1]      last ghci> last [5,4,3,2,1]   1  init ghci> init [5,4,3,2,1]   [5,4,3,2]          Retorna o primeiro elemento da lista. Retorna a calda da lista, ou, não exibe o primeiro elemento. Retorna o último elemento da lista. Retorna todos os elementos da lista menos o último.
  • 64. Operação com Listas length ghci> length [5,4,3,2,1]   5     reverse ghci> reverse [5,4,3,2,1]   [1,2,3,4,5]      elem ghci> 4 `elem` [3,4,5,6]   True   ghci> 10 `elem` [3,4,5,6]   False          Retorna o comprimento da lista. Inverte os elementos da lista. Verifica se um elemento está presente na lista.  
  • 65. Operação com Listas ghci> [1..20]   [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]    ghci> ['a'..'z']   &quot;abcdefghijklmnopqrstuvwxyz“    ghci> ['K'..'Z']   &quot;KLMNOPQRSTUVWXYZ&quot;               Selecionando intervalo de elementos em listas.  
  • 66. Tuplas Tuplas são usadas quando se sabe exatamente quantos elementos desejamos combinar, independente do seu tipo. first ghci> fst (8,11)   8   ghci> fst (&quot;Wow&quot;, False)   &quot;Wow&quot; zip ghci> zip [1,2,3,4,5] [5,5,5,5,5]   [(1,5),(2,5),(3,5),(4,5),(5,5)]   ghci> zip [1 .. 5] [&quot;one&quot;, &quot;two&quot;, &quot;three&quot;, &quot;four&quot;, &quot;five&quot;]   [(1,&quot;one&quot;),(2,&quot;two&quot;),(3,&quot;three&quot;),(4,&quot;four&quot;),(5,&quot;five&quot;)] Recebe um par e retorna o primeiro elemento.   Podem conter combinação de vários tipos .   Utilizado para combinar os elementos de duas listas.
  • 67. Funções ” x” é o nome da função. Os tipos dos 4 argumentos da função. O último tipo especificado identifica o tipo de dado a ser retornado. As definições de funções em Haskell podem ser feitas por meio de uma sequência de equações. <nome da função ><corpo> x : : Int -> Int -> Float -> Bool -> Int add :: Int -> Int -> int add x y = x + y
  • 68. Funções Guards é uma característica na definição de funções, que exploram a capacidade de se inserir condições que são utilizadas como alternativas para a função. guard. A função max retorna o maior valor entre dois números. max : : Int -> Int -> Int max x y | x >= y = x se x >= y então retorne x | otherwise = y caso contrário, retorne y
  • 69. Criando Funções É possivel criar suas próprias funções: Salvando a função como nome.hs é possível executá-la posteriormente. Função que recebe um número e multiplica ele por dois: doubleMe x = x + x ghci> nome:   [1  de  1] Compilando principal              (nome.hs, interpretado)   Ok, módulos carregados: Main.   ghci> doubleMe 9   18   ghci> doubleMe 8,3   16,6  A mesma pode ser utilizada com números de qualquer tipo.
  • 70. Criando Funções É possível também chamar funções dentro de funções. doubleUs y = x *2 + y *2 ghci> doubleUs 4 9   26   ghci> doubleUs 2,3 34,2   73,0   ghci> doubleUs 28 88 + doubleMe 123   478   Sendo assim é possível redefinir uma função. doubleUs x y = doubleMe x + y doubleMe  
  • 71. Polimorfismo Há polimorfismo universal, a função possui um tipo genérico e a mesma definição é usada para vários tipos. A função length pode retornar tanto o tamanho de uma String, quanto de uma Lista. Basta declarar e definir as funções com o mesmo nome, porém com os argumentos próprios para cada objetivo: length : : String -> Int length : : [a] -> Int
  • 72. Classes A definição de uma classe consiste em: class <nome_da_classe> <tipo_de_entrada> where <assinatura da classe> Exemplo: Class V a where toString a : : a -> String size a : : a -> Int Haskell permite que o usuário, programador, crie alguns outros tipos denominados Classes, que funcionam como tipos de dados abstratos. O usuário tem total liberdade para definir inúmeros tipos de classes diferentes. A assinatura da classe define as funções que poderão ser aplicadas aquela classe. ” a” é uma variável que representa qualquer tipo de dado. “ V” é o nome da classe.
  • 73. Verificação de Tipos Tanto os compiladores quanto os interpretadores Haskell implementam o mecanismo de checagem forte de tipos de dados , devido a tamanha variedade de tipos. Monomórfico Polimórfico
  • 74. Verificação de Tipos- Monomórficos f : : s -> t, onde a função f deve ser aplicada sobre um argumento de tipo s e resultar numa expressão do tipo t. A checagem de tipos monomórficos, isto é, sem polimorfismo. ” e” é uma expressão que pode ser um literal, uma variável ou constante, ou pode ser construído aplicando uma função sobre seus argumentos, que são cada um também expressões.
  • 75. Verificação de Tipos- Monomórficos A verificação das expressões naturalmente acaba assumindo uma característica recursiva; O analisador de expressões do compilador/interpretador deve descobrir o que pode ser uma expressão em Haskell e expandir numa árvore até que se obtenha a mais simples declaração dos tipos. Com esta informação, basta aplicar as regras que estão descritas na definição da própria função e compará-las com os tipos de dados informados na expressão raiz. Deve-se considerar os quesitos: - o valor ei retornado deve ser do tipo t; - p padrão de argumentos pj deve ser consistente com os tipos ti indicados na assinatura da função;
  • 76. Verificação de Tipos- Polimórficos Para realizar a verificação de tipos em funções polimórficas, o Haskell lança mão do conceito de unificação . Assim como em linguagens lógicas, uma unificação ocorre quando o analisador de expressões do compilador/interpretador consegue determinar quais variáveis assumirão um determinado argumento genérico, e também de qual tipo dedado será este argumento.
  • 77. Verificação de Tipos- Polimórficos A função soma recebe dois argumentos que podem ser de tipos quaisquer, temos nos exemplos a chamada da função com tipos de dados inteiros e também com tipos de ponto flutuante. Realizar a unificação sobre esta função significa que, ao chamar soma, o primeiro argumento &quot;fecha&quot; com a, o segundo com b e o resultado com c. Isto permite descobrir como posicionar os argumentos para uma função polimórfica. Agora vejamos um caso mais complexo. Considere a função f abaixo: f : : (a -> b) -> [a] -> [b] Ao chamar f com parâmetros Char -> Int, a unifica com Char e b com Int. Isto vale para toda a expressão, assim teremos: f : : (Char -> Int) -> [Char] -> [Int] Note como o Haskell avalia expressões polimórficas, e também o custo adicionado para realizar o processo de unificação.
  • 79. Main
  • 80. Declaração Os símbolos “—” “{- -}” comentários. Declara uma nova função, especificando seu tipo. O símbolo :: pode ser lido como “é do tipo...&quot; Determina que valor tem o valor 35. Determina que square é uma função de Int para Int . Equação que define a função. Define o resultado, x*x , da aplicação de square sobre x (argumento). Nomes de funções começam com letras minúsculas. Nomes de tipos começam com letras maiúsculas. 1 {----------------------------} 2 -- example.hs 3 ---------------------------- 4 valor :: Int 5 valor = 35 6 7 square :: Int -> Int 8 square x = x * x 9
  • 81. Condição Equação condicional, Os símbolo “|” , “=“ são utilizados para emular o comando de seleção. O valor à direita de “=“ é retornado se a condição for verdadeira. Determina que mystery é um função que recebe 3 Objetos Int e retorna True ou False Determina que maxx é uma função que recebe 2 objetos Int e retorna Int . 1 {---------------------------- 2 -- example.hs ----------------------------} 4 mystery :: Int -> Int -> Int -> Bool 5 mystery a b c = (a==b) && (b==c) 6 7 maxx :: Int -> Int -> Int 8 maxx m n 9 | m >= n = m 10 | otherwise = n
  • 82. Cálculos Como cálculos são efetuados em Haskell? A comparação é feita com os valores de a e b, depois b com c o resultado é a comparação da 1 ˚ sentença com a segunda. mystery a b c = (a == b) && (b == c) mystery 5 8 8 = (5==8) && (8==8) = False && True = False mystery 9 9 9 = (9==9) && (9 == 9) = True && True = True
  • 83. Exemplo envolvendo equação condicional: Cálculos maxx m n | m >= n = m | otherwise = n maxx 7 4 = 7 >= 4 = True = 7 maxx 12 45 = 12 >= 45 = False = otherwise = True = 45
  • 84. Quick Sort em Haskell Se a lista é vazia, não há nada a ordenar . s é o 1 o elemento da lista que é utilizado com pivo. xs representa o restante da lista. A lista restante é dividida em 2 partes: a primeira contém apenas os elementos de xs que são menores ou igual a s. A segunda, contém apenas os elementos de xs que são maiores. As duas listas são ordenadas recursivamente e o resultado é obtido concatenando a primeira lista (ordenada), com a lista que contém s e a segunda lista (ordenada.) qsort [] = [] qsort ( s : xs ) = qsort [ x | x <- xs , x < s] ++ [s] ++ qsort [ x|x <- xs, x >= s ]
  • 85. Interação Para escrever programas interativos que leem dados a partir do teclado e escrevem na tela, são necessários: IO Programas interativos podem ser escritos em Haskell usando tipos que podem envolver efeitos colaterais - IO . interactive program inputs outputs keyboard screen
  • 86. HUGS HUGS Interpretador; Escrito em C; Portável; Leve; Ideal para iniciantes;
  • 87. GHC GHC Interpretador e Compilador; Escrito em Haskell; Menos portável; Mais lento; Exige mais memória; Produz programas mais rápidos;
  • 88. O Compilador: GHC O compilador em si é escrito inteiramente em Haskell. Estrutura Geral Diagrama de blocos da sua estrutura de alto nível GHC é empacotado como um binário único; GHC é compilado, sem o seu front-ends , como uma  biblioteca; Pode ser importado por qualquer front-ends de programas Haskell.
  • 89. O Compilador: GHC HscMain: Lida com a compilação de um único módulo; Gerente de compilação:   Gerencia a compilação de vários módulos; Ela possui uma interface chamada de  API GHC ;  GHCi: Ambiente interativo, é implementado no  compilador / ghci / InteractiveUI.hs  ; Make: É um cliente da API do GHC, e é executada em  compilador / main / Main.hs ; M: Gerador de dependência Makefile , também é cliente da API do GHC, e é implementado no  compilador / main / DriverMkDepend.hs ; &quot;one-shot mode“ : Onde o GHC compila cada arquivo na linha de comando em separado (por exemplo , Foo.hs c GHC);   Este modo ignora a API do GHC;
  • 90. O GHC API Coordenam a compilação de vários módulos; API GHC suporta apenas um cliente que é na verdade a execução do código; A sequência típica da API do GHC é algo como o seguinte: Criar uma nova sessão:  newSession; Definir os flags:  getSessionDynFlags, setSessionDynFlags; Adicione algumas  tags :  setTargets, addTarget, guessTarget; Realizar  Análise de dependência :  depanal; Load (compile) os arquivos de origem:  load ;
  • 91. Sequência Tags As tags especificam a localização da fonte de arquivos ou módulos no topo da árvore de dependência; Análise de dependência A fase de análise de dependência determina todos os arquivos fonte Haskell que vão ser compilados ou carregados na sessão atual, percorrendo as dependências transitivas das tags .   Este processo é chamado de  downsweep  porque estamos atravessando a árvore de dependência das metas; Carregando (compilação) dos Módulos Quando a análise de dependência é completa, os módulos são carregados chamando load ; Finalmente, todo os objetcs codes são carregados junto com os byte-code, todos juntos na memória;  Chama-se o linker Link externo para gerar o código objeto em um binário;
  • 92. Tipos de dados-chave A chave para a compreensão do GHC é compreender os seus tipos de dados-chave.
  • 93. GHC : O Code Generator Storage Manager; Generated Cmm Naming Convention; Modules; Memory and Register Management; Function Calls and Parameter Passing ; Special runtime support ;
  • 94. GHC : Storage Manager
  • 95. GHC: A disposição dos objetos Heap Todos os objetos têm uma pilha de layout básico;   O diagrama abaixo mostra o layout de um objeto de heap : Um objeto de heap sempre começa com um  cabeçalho ; O cabeçalho é o  ponteiro de informações , que aponta para a tabela de informação; O compilador precisa saber o layout de objetos de heap, essa informação é passada para o compilador em tempo de execução
  • 96. Tabelas Info A tabela info contém todas as informações do estado atual no tempo de execução:
  • 97. Tabelas Info closure type É uma constante que descreve o tipo de fechamento (de função, de conversão, o construtor, etc.) ; SRT bitmap Campo é utilizado para apoiar o Garbage Collection ; Layout: Campo descreve o layout da carga para o Memory Manager ;
  • 98. Tabelas Info Alguns tipos de objeto adicionam mais campos ao final da tabela de informações, nome das funções, endereços de retorno; Note que a tabela de informação é imediatamente seguido pelo código de entrada. Isto reduz o tamanho da tabela de informações e elimina uma ponteiro indireto para o código de entrada;
  • 99. Objetos Dinâmicos X Estáticos Objetos caem em duas categorias: Dinâmica  : Objetos residem no heap , e pode ser movido pelo coletor de lixo; Objetos dinâmicos têm um tamanho mínimo, pois cada objeto deve ser grande o suficiente para ser substituído por um ponteiro de encaminhamento ( Forwarding pointers ) durante a GC; Estático: Objetos residem no código objeto compilado; Eles nunca são movidos, porque os ponteiros para objetos estão espalhadas através do código objeto; Objetos estáticos têm um campo adicional, chamado de  campo link estático . O campo de link estático é usado pela GC link para todos os objetos estáticos em uma lista, e assim que ele pode dizer se ela tem visitado um determinado objeto estático ou não; Para saber se um determinado objeto é estático ou dinâmico, usa-se a macro HEAP_ALLOCED ()  ;
  • 100. Layout da pilha Cada objeto TSO  contém uma pilha; A pilha de um TSO cresce para baixo; A pilha consiste de uma sequência de  quadros de pilha  (às vezes também chamados  registros de ativação ), onde cada quadro tem o mesmo layout como um objeto de heap: Objeto  TSO  é: uma Thread do estado do objeto;   Ele representa o estado completo de um segmento, incluindo a sua stack;
  • 101. Layout da pilha O  SRT   = Campo de ponteiro para a tabela de referência estático (SRT);
  • 102. Garbage Collection O GC é projetado para ser flexível, suportando muitas maneiras de ajustar o seu comportamento; GC Geracional, com um número selecionável de gerações em tempo de execução: (G + RTS-<n>-RTS, onde n> = 1). Atualmente ele é um colecionador de gerações tradicional, onde cada coleta recolhe uma determinada geração e as gerações mais jovens. A pilha cresce em armazenamento de um   alocador de blocos ;
  • 103. Alocador de Blocos O alocador de blocos é o responsável por prover a flexibilidade do GC; É o gestor de armazenamento; Ao invés de manter a nossa pilha em uma única região contígua de memória, ou uma região contígua por geração, conseguimos listas ligadas de blocos de memória; Gerenciar regiões contíguas é difícil, especialmente quando você quiser mudar o tamanho de algumas áreas. Um arranjo de armazenamento de bloco-estruturada tem várias vantagens: Redimensionamento áreas de memória é fácil: basta mais blocos para a lista; Gerenciamento de objetos grandes, sem copiar é fácil: atribuir a cada uma um bloco completo, e usar o bloco de ligação para a cadeia juntos; Memória livre pode ser reciclado mais rapidamente, porque é um bloco de um bloco; O conceito baseia-se na propriedade que a maioria dos objetos de dados são significativamente menores que um bloco, e só raramente precisamos alocar objetos que se aproximam ou excedem o tamanho de um bloco.
  • 104. Alocador de Blocos Estrutura de blocos Cada bloco possui um: bloco descritor , que contém informações sobre o bloco: o seu campo de ligação, que a geração a que pertence, e assim por diante. Isso é semelhante ao conhecido técnica &quot;BiBOP&quot; (Big Bag de paginação), onde os objetos com marcas semelhantes são reunidos em uma página de modo a evitar a necessidade de armazenar uma etiqueta individual com cada objeto. Megablocks de 1Mb de tamanho (m = 20) com blocos de 4k de tamanho (k = 12)
  • 105. Garbage Collection A política de coleta de pilha é runtime-ajustável: Você pode selecionar o tamanho de uma geração começa antes que ele seja coletado por meio doRTS + F-<n>-RTS opção, onde <n> é um fator de geração, o tamanho da última vez que foi coletada. O valor padrão é 2, que é uma geração é permitido dobrar de tamanho, antes de serem recolhidos; O GC é uma única thread:   Quando o RTS detecta a pressão de memória GC para todos os tópicos Haskell e um segmento que faz a coleta de lixo e, em seguida, reinicia todos os outros segmentos suspenso; Gerações O GC GHC é um colecionador de gerações. O número de gerações é definido como 2 por padrão e que são referidos como gen 0 e gen 1. gen 0 tem novos objetos, objetos que sobrevivem a coletas de Gen 0 são promovidos a um gen. Objetos antigos residir no gen 1.
  • 106. Garbage Collection - Estruturas Blocos e blocos Mega O GC aloca memória do sistema operacional em pedaços 1 Mb de tamanho, megablocos, que então se divide em. Cada página 4k é chamado de bloco e está associada a um bloco descripter(BD) . O BD mantém informações sobre um bloco;
  • 107. Garbage Collection - Estruturas Passos Gerações GHC são divididos em etapas; A última geração, o mais velho tem apenas um passo; A coleta de lixo acontece ao nível das gerações; Então, quando você diz que está coletando gen 0, que é recolher todas as etapas de geração 0. Se você está coletando gen 4, então você está coletando todas as etapas de geração de 0 a gen 4.  Objetos que sobrevivem a uma coleta são promovidos ao escalão imediatamente superior;
  • 108. Garbage Collection - Estruturas
  • 109. Garbage Collection - Estruturas
  • 110. Espaço das Classes Normal Overlap Closed Local Normal Global Implicit Parameters Haskell GHC Methods Dependência local
  • 111.  
  • 114. verification : bytecode :: typechecking : source code YHC
  • 115. YHC
  • 116. DICAS Ao definir uma nova função em Haskell, é útil começar por escrever o seu tipo; Dentro de um script, é boa prática para indicar o tipo de cada nova função definida; Ao afirmar os tipos de funções polimórficas que usam números, como a igualdade ou ordenações, tome o cuidado ao incluir as restrições de classe;
  • 117. Avaliação Alta Flexibilidade : De acordo com a Tese de Church, todo e qualquer problema resolvido imperativamente possui uma resolução indutiva; Tipagem : Haskell é extremamente tipada , sendo conhecido como calculadora funcional.Expressões são reduzidas tendo por base o cálculo lambda. Portabilidade : Interpretadores ou compiladores trabalham em diversos tipos de arquitetura e sistemas operacionais.
  • 118. Haskell X Outras Linguagens Haskell separa a definição de um tipo a partir da definição dos métodos associados a esse tipo; Uma classe em C++ ou Java normalmente definem a estrutura de dados (variáveis, membro) e as funções associadas com a estrutura (os métodos). Em Haskell, essas definições são separados; As classe definidas por Haskell correspondem às funções virtuais em uma classe C++ e similares a uma interface Java; Cada instância de uma classe fornece a sua própria definição de cada método, os padrões de classe correspondem às definições padrão para uma função virtual na classe base; Como uma declaração de interface, uma declaração de classe Haskell define um protocolo para a utilização de um objeto em vez de definir um objeto em si;
  • 119. Haskell X Outras Linguagens C++ e Java anexam as informações de identificação (como um vtable) para a representação de tempo de execução de um objeto. Em Haskell, essa informação está ligado, logicamente, em vez de física para valores, através do tipo de sistema; Não há controle de acesso (tais como público ou privado, de classe componentes) incorporados ao sistema de classe Haskell. Em vez disso, o módulo do sistema deve ser usado para esconder ou revelar os componentes de uma classe.
  • 121. Curiosidades Vídeos: http://www.youtube.com/watch?v=X4-212uMgy8 http://www.youtube.com/watch?v=A1wtQ_mYHHo&feature=related
  • 122. Curiosidades GHC 6.10.4 Compilador de Haskell; GHCi 6.10.4 O interpretador de bytecode e um ambiente interativo para Haskell; Um depurador interativo para Haskell;
  • 123. Curiosidades Tratamento para Computação paralela:
  • 125. Vantagens Suporte à simultaneidade e paralelismo ; Apoiado por uma grande biblioteca de módulos de pacotes; Fornecido com depuradores e profilers ; Livremente disponível (código-fonte aberto, pacote de desenvolvimento completo);
  • 126. Vantagens Fortemente Tipada e Estática; Avaliação Lazy; Polimorfismo Universal Paramétrico; Função (superior e parcial); Ausência de desvios incondicionais;
  • 127. Desvantagens Requer muita memória; Execução lenta;
  • 128. Conclusão Neste seminário tivemos a oportunidade de explanar os principais aspectos de implementação da linguagem funcional Haskell. Além disso também foi discutido aspectos de programação do ponto de vista do usuário da linguagem. Em geral as linguagens funcionais assumem um papel extremamente específico em projetos de desenvolvimento de software, na maioria dos casos, aplicações com fins especiais conseguem tirar proveito do poder do paradigma funcional. O Haskell é funcional mas futuramente estenderá a aplicação suportando vários paradigmas na mesma linguagem, podendo-se programar de forma funcional, imperativa ou orientada a objetos. Naturalmente este suporte sempre possui uma base funcional e através dela se obtém uma abstração de outros paradigmas, porém é fácil notar toda a força do Haskell que dá ao programador uma série de recursos de forma extremamente simples e principalmente didática, Possibilita que a linguagem seja facilmente utilizada tanto no âmbito do ensino de programação em linguagens funcionais, como na criação de grandes projetos de aplicativos comerciais mais complexos. Haskell nos dá todo o poder do paradigma funcional com a facilidade de implementação e clareza de código.
  • 129. Bibliografia The Haskell Home Page: www.haskell.org Haskell Reference: www.zvon.org/other/haskell/Outputglobal Haskell GHC: http://hackage.haskell.org/trac/ghc/wiki/