learnhaskell/guide-pt.md
Chris Allen 268f5a9a19 cleanup
2015-05-07 14:52:14 -05:00

34 KiB

O Guia

Este é o caminho que recomendo para se aprender Haskell.

Uma coisa para se lembrar sempre: não se preocupe com aquilo que não entender imediatamente. Apenas continue.

Comunidade

Nosso canal no IRC é #haskell-beginners no Freenode.

Cliente web para IRC aqui.

Listas de e-mails relacionadas a Haskell.

Diretrizes para a Comunidade

Leia a postagem de Chris Done sobre ensino (Em inglês)

Seja gentil e cortês. Ser cruel ou rude assusta as pessoas e as desencoraja a participar.

Criticismo barato beneficia apenas a pessoa que o emite, não a pessoa que o recebe.

Não descreva coisas como "fáceis" ou "triviais". Você fará pessoas se sentirem mal por terem que trabalhar duro para progredirem. Pessoas que aprendem lentamente frequentemente são aquelas que aprendem melhor, isso é algo para ser celebrado!

Sem surpresa fingida. Não se faça de surpreso quando alguém diz que não sabe alguma coisa. Essa pessoa se sentirá mal e você terá conseguido nada além de se sentir afiado.

Sem "bom, na verdade". Quando alguém diz algo que está quase - mas não totalmente - correto, e você diz, "bom, na verdade..." e então faz uma correção pequena. Isso é especialmente incômodo quando a correção não tem relação com o assunto conversado. Isso não significa que o Recurse Center não é sobre a busca de verdade ou que nós não nos importamos em ser precisos. Quase todos esses "bom, na verdade" são com intenção de se aparecer, não em benefício da verdade.

Sem essa de dirigir no banco de trás. Se você vê as pessoas trabalhando em um problema, você não deveria lançar conselhos intermitentemente. Deixe-as trabalhar a menos que alguém peça por ajuda. Evitar interrupções é um dos propósitos fundamentais do #haskell-beginners

Sem "-ismos" sutis. Racismo, sexismo, homofobia, transfobia, e outros tipos de preconceito não são bem vindos e não serão tolerados.


Diretrizes do manual do Recurse Center. Obrigado por disponibilizar isso, Recurse Center.

O que é Haskell, GHC, e Cabal?

Haskell é uma linguagem de programação como é definido nos relatórios, o mais recente sendo o de 2010. O relatório está disponível como onlinereport.

GHC

GHC é o meio mais popular de se trabalhar na linguagem Haskell. Ele inclui um compilador, REPL (interpretador), gerenciamento de pacotes, e outras coisas mais.

Cabal

Cabal realiza gerenciamento de projetos e resolução de dependências. É como você instalará projetos, tipicamente na própria sandbox deles.

Cabal é equivalente ao Bundler do Ruby, pip do Python, NPM do Node.js, Maven, etc. O GHC é responsável pelos pacotes propriamente ditos, o Cabal escolhe quais versões serão instaladas.

Configurações iniciais

Ubuntu

Este PPA é excelente e é o que eu uso em todas as máquinas Linux de desenvolvimento e produção.

Especificamente:

$ sudo apt-get update
$ sudo apt-get install python-software-properties # v12.04 e abaixo
$ sudo apt-get install software-properties-common # v12.10 e acima
$ sudo add-apt-repository -y ppa:hvr/ghc
$ sudo apt-get update
$ sudo apt-get install cabal-install-1.20 ghc-7.8.4 happy-1.19.4 alex-3.1.3

Então adicione o seguinte ao seu $PATH (bash_profile, zshrc, bashrc, etc):

~/.cabal/bin:/opt/cabal/1.20/bin:/opt/ghc/7.8.4/bin:/opt/happy/1.19.4/bin:/opt/alex/3.1.3/bin

Opcional: Você também pode adicionar .cabal-sandbox/bin ao seu path. Código que você está desenvolvendo ativamente estará disponível a partir da sua linha de comando. Isso funciona apenas quando o diretório de trabalho atual é uma sandbox do cabal.

Debian

Usando Ubuntu PPA

Se você não está usando o stable, pode seguir os mesmos passos do Ubuntu, mas precisará executar um comando adicional. Imediatamente após o sudo add-apt-repository -y ppa:hvr/ghc, execute:

$ sudo sed -i s/jessie/trusty/g /etc/apt/sources.list.d/hvr-ghc-jessie.list

Para outras versões do Debian, apenas substitua todas as ocorrências de jessie com o nome da sua versão no comando acima.

Se, por alguma razão, o arquivo /etc/apt/sources.list.d/hvr-ghc-jessie-list não existir, então /etc/apt/sources.list deve conter uma linha assim:

deb http://ppa.launchpad.net/hvr/ghc/ubuntu jessie main

Substitua jessie por trusty nesta linha.

Compilação manual

Você pode seguir este guia escrito para Mac OS X:

Notas:

  • Configure o seu prefixo adequadamente quando configurar o ghc.
  • Em vez de pegar o binário do cabal-install, pegue o código fonte e execute o script bootstrap.sh.

Fedora 21

Para instalar o Haskell 7.8.4 a partir do repositório não-oficial (versões 22+ do Fedora vão incluí-lo no oficial):

$ sudo yum-config-manager --add-repo \
> https://copr.fedoraproject.org/coprs/petersen/ghc-7.8.4/repo/fedora-21/petersen-ghc-7.8.4-fedora-21.repo
$ sudo yum install ghc cabal-install

Como dito na página do copr petersen/ghc-7.8.4 este ghc não pode ser instalado em paralelo com o ghc do Fedora/EPEL.

Arch Linux

Para instalar o Haskell dos repositórios oficiais no Arch Linux, execute

$ sudo pacman -S cabal-install ghc happy alex haddock

Gentoo

No Gentoo, você pode instalar os componentes individuais da Plataforma Haskell através do Portage. Se você usar ACCEPT_KEYWORDS=arch (em vez de ACCEPT_KEYWORDS=~arch), o Portage vai instalar versões antigas dos vários componentes do Haskell. Com isso em mente, se você usar ACCEPT_KEYWORDS=arch, adicione o seguinte ao /etc/portage/package.keywords:

dev-haskell/cabal-install
dev-lang/ghc

Uma vez que isso foi feito,

$ emerge -jav dev-lang/ghc dev-haskell/cabal-install

O Gentoo mantém uma versão "estável" (leia-se: antiga) do cabal-install na árvore do Portage, então você vai querer usar o cabal-install para instalar a versão mais recente. Note que as contrabarras são intencionais.

$ \cabal update                # As contrabarras
$ \cabal install cabal-install # são intencionais

Agora você instalou o cabal num escopo global com o portage, e localmente no seu diretório home com o cabal-install. O próximo passo é garantir que quando você executar o comando cabal num terminal, seu shell vai executar a versão recente que está no seu diretório home. Para isso, as seguintes linhas devem ser adicionadas ao arquivo de configuração do seu shell:

PATH=$PATH:$HOME/.cabal/bin
alias cabal="$HOME/.cabal/bin/cabal"

Se não sabe qual shell é o seu, provavelmente ele é o Bash. Se você usa o Bash, o arquivo a ser editado é o ~/.bashrc. Se você usa o Z-shell(zsh), o arquivo é o ~/.zshrc. Você pode executar o seguinte comando para descobrir qual é o seu shell.

echo $SHELL | xargs basename

Eu uso o zsh, então esse comando produz zsh como saída.

Uma vez que você fez tudo isso, você vai querer instalar as ferramentas adicionais alex e happy.

$ cabal install alex happy

Parabéns! Agora você tem uma instalação funcional do Haskell!

Mac OS X

10.9

Instale o app GHC for Mac OS X, que inclui o GHC e o Cabal. Ele traz instruções sobre como adicionar o GHC e o Cabal ao seu path depois de ter arrastado o .app para algum lugar.

10.6-10.8

Faça a instalação da distribuição binária descrita neste arquivo.

Windows

Não esqueça de rodar o instalador como administrador, já que ele vai querer instalar no seu Arquivos de Programas.

Usuários de outros Linux

Baixe as últimas distribuições binárias para o cabal e ghc:

Cursos Iniciais

Curso cis194 do Yorgey

Faça este primeiro, esta é a minha recomendação de como ser introduzido ao Haskell.

Disponível online.

O curso de Brent Yorgey é o melhor que eu encontrei até agora. Esse curso é importante porque ele não só vai equipá-lo a escrever Haskell básico mas também vai ajudá-lo a entender parser combinators.

A única razão pela qual você não deveria começar com o cis194 é se você não for um programador ou se for um que é inexperiente. Se esse é o caso, comece com o livro do Thompson e depois o cis194.


Curso NICTA

Este é o curso que recomendo fazer após o curso cis194 do Yorgey.

Disponível no github aqui.

Isso vai reforçar e lhe dar experiência implementado diretamente as abstrações introduzidas no cis194. Essa prática é crítica para alguém se tornar confortável com o uso diário de Functors/Applicatives/Monads/etc em Haskell. Fazer o cis194 e então o curso do NICTA representa a recomendação fundamental do meu guia, e é como eu ensino Haskell para todo mundo.


Curso suplementar cs240h

Fornece mais materiais em tópicos intermediários

Disponível online.

Essa é a versão online do curso que o Bryan O'Sullivan leciona em Stanford. Se você não sabe quem ele é, dê uma olhada em metade das bibliotecas que qualquer aplicação em Haskell acaba precisando e o nome dele estará nela. Se você já fez o curso do Yorgey, são particularmente interessantes os módulos sobre tipos fantasma (phantom types), controle de fluxo da informação (information flow control), extensões de linguagem (language extensions), concorrência, pipes e lenses.


Material de referência para os três cursos

Learn You a Haskell for Great Good (LYAH) e o Real World Haskell (Obrigado, bos!) estão disponíveis online.

Eu recomendo o RWH como referência (livro grosso). Os capítulos sobre parsing e monads são ótimos para entender onde monads são úteis. Outras pessoas já disseram que gostaram muito deles. Talvez seja um bom seguimento para aplicações práticas depois que você já está acostumado com o essencial de Haskell.

O que os açúcares sintáticos <- / do / compreensão de listas fazem exatamente?

Excelente artigo.

Para entender listas e folds

Para aprender typeclasses comuns

Útil para entender Functor, Applicative, Monad, Monoid e outras typeclasses em geral, mas também conceitos de Teoria das Categorias específicos à Hask.

Entendendo mensagens de erro básicas do Haskell

Avaliação preguiçosa, estrita, recursão guardada

Breve demonstração

let a = 1 : a -- recursão guardada, (:) é preguiçoso
let (v : _) = a -- e é possível fazer *pattern matching*

> v
1
> head a -- head a == v
1

let a = 1 * a -- recursão não guardada, (*) é estrito
> a
*** Exception: <<loop>>

IO

Comentário de thread no Reddit por glaebhoerl

Nota importante: o GHC precisa esconder a representação do símbolo de estado atrás de um tipo abstrato de IO porque o símbolo de estado sempre deve ser usado linearmente (não duplicado ou abandonado), mas o sistema de não pode reforçar isso. Clean, uma outra linguagem preguiçosa semelhante a Haskell, tem tipos de unicidade (que são como tipos lineares e possivelmente diferente em maneiras das quais não estou informado), e eles expõe a "passagem do Mundo" diretamente e fornece a monad (não abstrata) apenas por conveniência.

monads e transformadores de monad (monad transformers)

Não faça esses até que você entenda typeclasses, Monoid, Functor e Applicative!

Implemente as monads da biblioteca padrão ( List, Maybe, Cont, Error, Reader, Writer, State ) por si mesmo para entendê-las melhor. Então talvez escreva um interpretador monádico para uma pequena linguagem de expressões usando o artigo Passo-a-passo em Monad Transformers (mencionado abaixo em 'monad transformers').

Escrever vários interpretadores apenas mudando a monad para mudar a semântica pode ajudar a entender o que está acontecendo.

Além disso, reimplemente Control.Monad. Funções como mapM ou sequence são boas oportunidades para praticar escrevendo código monádico genérico.

O curso NICTA pode ser usado como um guia para esse processo, o que também vai envolver escrever seu próprio Applicative.

Créditos:

  • comentário no Reddit feito por htmltyp e Crandom aqui.

  • comentário no Reddit feito por jozefg aqui.

Monad Transformers

Testando, testes, especificações, teste de propriedades/generativo

  • Este tutorial por Kazu Yamamoto é fantástico.

  • Simple-Conduit: Biblioteca simples e boa para aprender como funciona streaming IO em geral, conhecimento transferível para bibliotecas como Pipes e Conduit.

Parsing em Haskell

Parsing e geração de JSON

Aeson é a solução padrão para parsing de JSON em Haskell. Disponível no hackage e github.

Algoritmos de Grafo e Estrutura de Dados

Ambiente de Desenvolvimento

Emacs

Vim

Sublime Text

Trabalhando com Cabal

Diretrizes do Cabal

O Cabal Hell (Inferno do Cabal) era um problema para usuário de Haskell antes da introdução das sandboxes. Instalar fora de uma sandbox vai instalar no package-db de seu usuário. Isso não é uma boa ideia, exceto para pacotes fundamentais como Cabal, alex e happy. Nada além disso deve ser instalado nos package-dbs do usuário ou global a menos que você saiba o que está fazendo.

Algumas melhores práticas para evitar o cabal hell estão disponíveis aqui.

Para experimentar um pacote ou iniciar um projeto, comece fazendo cabal sandbox init num novo diretório.

Colocando brevemente:

  • Sempre use sandboxes para instalar novos pacotes, compilar projetos novos ou existentes, ou iniciar experimentos.
  • Use o cabal repl para iniciar uma instância do ghci com escopo limitado ao projeto.

A abordagem baseada em sandbox que sugiro deve evitar problemas em dependência de pactes, mas é incompatível com a maneira que a Plataforma Haskell fornece pacotes pré-compilados. Se você ainda está aprendendo Haskell e não entende como o ghc-pkg e o Cabal funcionam, evite a plataforma e em vez dela use as instruções para instalação no começo deste guia.

Stackage

Para qualquer usuários (principalmente os do Yesod) que tem problemas de compilação, considere o Stackage.

  • Um bom sumário do Stackage aqui.

Na opinião do autor, o Stackage é geralmente mais útil do que o cabal freeze.

Hoogle e Haddock

Pesquise código pela type signature

O motor de buscas Hoogle pode pesquisar pelos tipos.

Por exemplo, olhe os resultados de busca para (a -> b) -> [a] -> [b] aqui.

Também hospedado pelo fpcomplete aqui.

Também o Hayoo (que por padrão tem tudo do hackage disponível para pesquisa).

Configurando sua própria instância local do Hoogle

Dê uma olhada aqui.

Haddock

  1. Conserte sua documentação do hackage

  2. Documentação v2 do Hackage

Perceba que essas postagens estão levemente desatualizadas: por exemplo, agora o Hackage exibe informação nova com destaque com informação de documentação e o estado da build.

O que você realmente precisa saber

Para fazer com que o haddocks inclua documentação para pacotes relacionados, você deve setar documentation: True no seu ~/.cabal/config. Se ele for deixado no padrão (False) ou setado para False, você vai precisar deletar todos os seus pacotes e reinstalar antes de gerar os haddocks.

Outra coisa para se ter em mente é que devido ao modo como o parâmetro $pkg é interpolado pelo cabal, não por você, os parâmetros html-location e content-location precisam estar em aspas simples e configurados num shell ou contidos num shell script. Eles não vão funcionar num Makefile, porque ele vai pensar que são variáveis para o Make!

#! /usr/bin/env sh

# You can write it one one line by skipping the backslashes
cabal haddock --hoogle --hyperlink-source                       \
 --html-location='http://hackage.haskell.org/package/$pkg/docs' \
 --contents-location='http://hackage.haskell.org/package/$pkg'

TravisCI

Se você é um grande fã do TravisCI como eu sou, então recomendo fortemente que considere o multi-ghc-travis como base para o travis.yml em seus projetos em Haskell.

Frontend/Javascript

Nós temos muita coisa nessa área! Existem três opções principais que eu recomendaria:

  • Haste um compilador de Haskell para Javascript

Qual linguagem frontend eu deveria usar?

GHCJS e Haste são ambos totalmente Haskell. O GHCJS vai funcionar com mais pacotes Haskell do que o Haste, mas isso não influencia muitos projetos de frontend. Purescript sequer é Haskell, então compartilhamento direto de código com seu backend não vai funcionar.

O custo em tempo de execução do GHC é o mais caro próximo dos 10KB (luite está trabalhando nisso). O Haste e o PureScript são competitivos.

O PureScript tem a melhor integração com as ferramentas JavaScript (ele usa gulp/grunt/bower), o GHCJS e o Haste se integram melhor com as ferramentas Haskell (Cabal).

Todos os três são ótimas escolhas e vão funcionar bem para a maior parte dos projetos de frontend.

Para um entendimento mais completo sobre avaliação preguiçosa, NF, WHNF

Artigos de pesquisa sobre cálculo lambda preguiçoso

Paralelismo/Concorrência

Lenses e Prisms

Depois de estar confortável em Haskell, considere seriamente aprender Lenses e Prisms, mesmo que somente como "usuário". Você não precisa aprender a teoria das categorias utilizada para que eles sejam úteis.

Muitos superestimam demais a dificuldade em se usar Lens. Qualquer um confortável com Functor/Foldable/Traversable (ou até mesmo só com o primeiro) pode usar lenses e prisms para tornar sua vida mais feliz.

Se você já fez algo como: (fmap . fmap) você está utilizando lenses na sua cabeça.

Eu recomendo estes dois tutoriais/introduções:

Olhe aqui para mais informações: Pacote Lens no hackage.

Esquemas de Recursão

Algumas das palavras *-morfismo que você já ouviu tratam na verdade de recursão. Nota - antes de se aventurar neste material, você deveria saber como implementar o foldr para listas e para pelo menos mais uma estrutura de dados, como uma árvore. (folds são catamorfismos) Saber como se implementa um unfold (anamorfismo) para a mesma estrutura vai facilitar um pouco as coisas.

Este material se encaixa com traversable e foldable.

GHC Core e tunando a performance

Teorias dos Tipos e das Categorias

Não é necessário saber isso para programar em Haskell, é apenas para quem se interessar!

Se você quiser um material complementar em teoria dos tipos e das categorias:

Livros

Outros tópicos divertidos

Parametricidade, polimorfismo ad-hoc vs. paramétrico, teoremas livres

Inicial e Final, DSLs, Finally Tagless

Comonads

Yoneda / CoYoneda

Proposições vs. Julgamentos (computação)

Tipagem dependente

Linkando binários estaticamente

Diálogos

Hospedado neste repositório.

Esses são tópicos bastante importantes e úteis. Olhe aqui para mergulhar mais fundo numa variedade de tópicos.