Avaliação da Unidade 2: Projeto hs2json¶
Esta atividade avaliativa consiste em construir um projeto completo em Haskell moderno, aplicando técnicas de desenvolvimento de bibliotecas, modularização em Cabal e testes baseados em propriedades com QuickCheck.
Tutorial guiado no site de tutoriais
O desenvolvimento completo do projeto é guiado pelo tutorial no site de tutoriais do LambdaGEO:
Construindo e Testando uma Biblioteca Haskell: JSON, Pretty Printing e QuickCheck
📋 Especificações do Projeto¶
Você deverá criar um projeto Cabal chamado hs2json estruturado como uma biblioteca reutilizável e uma suíte de testes robusta.
O projeto deve conter as seguintes funcionalidades mínimas:
A. Tipo de Dados e Accessors (SimpleJSON.hs)¶
O arquivo src/SimpleJSON.hs deve definir o tipo algébrico de dados JValue que representa JSON, além de funções para extração segura de dados (accessors):
getString :: JValue -> Maybe StringgetInt :: JValue -> Maybe IntgetDouble :: JValue -> Maybe DoublegetBool :: JValue -> Maybe BoolgetObject :: JValue -> Maybe [(String, JValue)]getArray :: JValue -> Maybe [JValue]isNull :: JValue -> Bool
B. O Pretty Printer JSON (Prettify.hs e PrettyJSON.hs)¶
Você deve desenvolver uma biblioteca de formatação baseada em um tipo abstrato Doc. O renderizador deve:
- Escapar strings corretamente (caracteres Unicode, quebras de linha
\n, tabs\t, etc.). - Imprimir objetos JSON formatados com indentação e quebra de linhas para fácil legibilidade.
C. Testes com QuickCheck (test/Spec.hs)¶
O projeto deve conter uma suíte de testes rodando via cabal test com, no mínimo:
- Implementação da Typeclass
Arbitrarypara o tipoJValuede forma a gerar dados aleatórios corretos e não-recursivos infinitos. - No mínimo 5 propriedades escritas para testar as invariantes da sua biblioteca (ex: idempotência de renderização, corretude dos escapes de string, corretude de acesso nas funções
get).
Cuidado ao limitar a recursão do gerador
JValue é recursivo através de listas (JObject [(String, JValue)], JArray [JValue]), o que é mais traiçoeiro do que parece. Usar sized para reduzir um contador n a cada chamada recursiva não basta: se você gerar os campos de JObject/JArray com listOf, o comprimento da lista é decidido pelo parâmetro de tamanho ambiente do QuickCheck (que cresce até 100 ao longo dos testes), não pelo seu n. O resultado não é um erro de compilação nem um teste que falha rápido — é o processo travar, consumindo memória sem fim, porque a árvore gerada cresce exponencialmente (profundidade limitada, largura não). A correção é envolver a chamada a listOf com resize (n \div` 2)`, para que o comprimento da lista também encolha com a profundidade — veja o Capítulo 9 (exercício 3) do tutorial de Haskell para o mecanismo completo, com exemplo de código.
⚙️ Requisitos do Repositório e Entrega¶
- Estrutura Cabal: O projeto deve compilar limpo rodando
cabal build. - Qualidade dos Testes: A suíte de testes deve rodar com sucesso via
cabal test. - Organização do Git: O histórico de commits no repositório GitHub deve ser incremental e refletir o avanço por etapas do desenvolvimento do projeto (Conventional Commits recomendado).
- Arquivo
README.md: Explicando claramente como clonar, compilar, testar e executar a aplicação.