Estrutura de Projetos com Stack e Haskell Moderno¶
No desenvolvimento industrial de Haskell, não compilamos arquivos avulsos usando ghc manualmente como no ambiente acadêmico. Em vez disso, utilizamos ferramentas de build modernas que gerenciam dependências, garantem reprodutibilidade e automatizam compilações e testes.
A ferramenta padrão da indústria hoje é o Stack.
🚀 O que é o Stack?¶
O Stack é um programa para gerenciar projetos Haskell. Ele se encarrega de:
- Instalar a versão correta do compilador GHC automaticamente para cada projeto (isolando-a de outras no sistema).
- Baixar e gerenciar dependências utilizando o Stackage, um repositório curado onde todas as bibliotecas são testadas juntas para garantir compatibilidade.
- Compilar, rodar executáveis e executar suítes de testes de forma simples.
📁 Estrutura de um Projeto Stack¶
Quando criamos um projeto novo rodando stack new hs2json, o Stack gera a seguinte árvore de diretórios:
hs2json/
├── app/
│ └── Main.hs # Ponto de entrada executável (função main)
├── src/
│ └── Lib.hs # Código-fonte da nossa biblioteca reutilizável
├── test/
│ └── Spec.hs # Suíte de testes automatizados
├── package.yaml # Configuração do projeto moderna (metadados e dependências)
├── stack.yaml # Configuração do Stack (fixa a versão do compilador GHC)
└── hs2json.cabal # Configuração gerada automaticamente (NÃO EDITAR)
Arquivos Principais de Configuração:¶
stack.yaml: Define oresolver, que especifica a versão do compilador GHC e a seleção compatível de pacotes do Stackage.package.yaml: A especificação moderna do seu pacote. Aqui você define:- Nome, autor, versão do projeto.
- Dependências globais (ex:
base,text,containers). - Módulos da Library (código em
src/). - Dependências e módulos do Executable (código em
app/que consome a library). - Configuração dos Tests (código em
test/que testa a library).
🛠️ Comandos Essenciais do Stack¶
Dentro do diretório do projeto:
| Comando | Descrição |
|---|---|
stack setup |
Baixa e instala a versão necessária do GHC (se ainda não estiver instalada). |
stack build |
Compila todo o projeto (biblioteca, executáveis e testes). |
stack run |
Executa o binário principal do projeto. |
stack test |
Executa a suíte de testes do projeto. |
stack ghci |
Abre o REPL interativo carregando todos os módulos e dependências do projeto. |
🧩 Escrevendo um Módulo Haskell Moderno¶
Para que os arquivos se enxerguem, cada arquivo .hs dentro de src/ deve declarar seu nome de módulo de forma correspondente ao seu caminho no sistema de arquivos.
Exemplo de um arquivo src/SimpleJSON.hs:
module SimpleJSON
( JValue(..)
, getString
) where
data JValue = JString String
| JBool Bool
deriving (Show, Eq)
getString :: JValue -> Maybe String
getString (JString s) = Just s
getString _ = Nothing
E para usá-lo em app/Main.hs:
module Main where
import SimpleJSON (JValue(..), getString)
main :: IO ()
main = do
let val = JString "Haskell Moderno"
print (getString val)
🔗 Transição: Da Teoria Acadêmica para o Desenvolvimento Modular¶
Na Unidade 1, você trabalhou com arquivos soltos compilados pelo ghc ou carregados no ghci. Essa abordagem é ideal para focar na sintaxe e conceitos puros da linguagem (como casamento de padrões, listas e recursão).
No entanto, no desenvolvimento real, lidamos com código dividido em múltiplos arquivos (módulos), dependências externas (como bibliotecas HTTP, bancos de dados ou frameworks de teste) e testes de unidade automatizados.
Nesta Unidade 2, usamos o Stack para unificar duas práticas fundamentais:
- Modelagem de Dados (SimpleJSON): Onde aplicamos os conceitos de tipos de dados algébricos e pattern matching para construir uma biblioteca de parsing e manipulação de objetos JSON reais (baseado no Capítulo 5 do Real World Haskell).
- Garantia de Qualidade (QuickCheck): Onde mostramos como testar propriedades matemáticas da nossa biblioteca de maneira automatizada (baseado no Capítulo 11 do Real World Haskell).
No próximo capítulo, iniciaremos a construção da nossa biblioteca SimpleJSON, aplicando as estruturas de projeto do Stack apresentadas aqui.