Ontem eu aprendi sobre uma nova ferramenta Haskell chamada Stack . À primeira vista, parece que faz o mesmo trabalho que Cabal. Então, qual é a diferença entre eles? A pilha é um substituto para o Cabal? Em quais casos devo usar Stack em vez de Cabal? O que Stack pode fazer que Cabal não pode?
haskell
cabal
haskell-stack
ZhekaKozlov
fonte
fonte
cabal-install
e usa empilhamento tanto quanto possível - pode haver alguma integração posterior com cabal-install em algum ponto e eu acho a comunidade não tem certeza se isso é uma coisa boa ou não, porque pode dividir a comunidade)Respostas:
Sim e não.
Stack usa os pacotes de empilhamento selecionados por padrão . Sendo assim, sabe-se que quaisquer dependências são construídas em conjunto, evitando problemas de conflito de versões (que, na época em que eram comuns na experiência de Haskell, costumavam ser conhecidos como "inferno da cabala"). Versões recentes do Cabal também possuem medidas para prevenir conflitos. Ainda assim, definir uma configuração de construção reproduzível na qual você sabe exatamente o que será retirado dos repositórios é mais simples com Stack. Observe que também há provisão para o uso de pacotes sem empilhamento, portanto, você está pronto para continuar, mesmo se um pacote não estiver presente no instantâneo de empilhamento.
Pessoalmente, gosto de Stack e recomendo a todos os desenvolvedores Haskell que o usem. Seu desenvolvimento é rápido . E tem um UX muito melhor. E há coisas que Stack faz que Cabal ainda não oferece:
stack build --fast --file-watch
. Isso será reconstruído automaticamente se você alterar os arquivos locais presentes. Usá-lo junto com a--pedantic
opção é um obstáculo para mim.Há uma boa postagem no blog explicando a diferença: Por que Stack não é Cabal? Embora Cabal tenha, nos anos que se passaram desde aquela postagem, evoluído de forma a superar alguns dos problemas discutidos lá, a discussão dos objetivos de design e filosofia por trás de Stack permanece relevante.
fonte
A seguir, irei me referir às duas ferramentas que estão sendo comparadas como cabal-install e stack . Em particular, usarei cabal-install para evitar confusão com a biblioteca Cabal , que é uma infraestrutura comum usada por ambas as ferramentas.
Em termos gerais, podemos dizer que cabal-install e stack são front-ends para o Cabal . Ambas as ferramentas tornam possível construir projetos Haskell cujos conjuntos de dependências podem entrar em conflito uns com os outros dentro dos limites de um único sistema. A principal diferença entre eles está em como abordam esse objetivo:
Por padrão, cabal-install irá, quando solicitado a construir um projeto, olhar para as dependências especificadas em seu
.cabal
arquivo e usar um solucionador de dependências para descobrir um conjunto de pacotes e versões de pacote que o satisfaçam. Este conjunto é retirado do Hackage como um todo - todos os pacotes e todas as versões, passadas e presentes. Assim que um plano de construção viável for encontrado, a versão escolhida das dependências será instalada e indexada em um banco de dados em algum lugar do~/.cabal
. Conflitos de versão entre dependências são evitados indexando os pacotes instalados de acordo com suas versões (bem como outras opções de configuração relevantes), de forma que diferentes projetos possam recuperar as versões de dependência de que precisam sem pisar nos calcanhares uns dos outros. Este arranjo é o queA documentação do cabal-install significa "compilações locais no estilo Nix" .Quando solicitado a construir um projeto, a pilha , em vez de ir para o Hackage, examinará o
resolver
campo destack.yaml
. No fluxo de trabalho padrão, esse campo especifica um instantâneo Stackage , que é um subconjunto de pacotes de Hackage com versões fixas que são conhecidas por serem mutuamente compatíveis. stack tentará então satisfazer as dependências especificadas no arquivo (ou possivelmente no arquivo - formato diferente, mesma função) usando apenas o que é fornecido pelo instantâneo. Os pacotes instalados de cada instantâneo são registrados em bancos de dados separados, que não interferem uns nos outros..cabal
project.yaml
Podemos dizer que a abordagem de pilha troca alguma flexibilidade de configuração por simplicidade quando se trata de especificar uma configuração de construção. Em particular, se você sabe que seu projeto usa, digamos, o instantâneo LTS 15.3, você pode ir para sua página Stackage e saber, de relance, as versões de qualquer pilha de dependência pode puxar do Stackage. Dito isso, ambas as ferramentas oferecem recursos que vão além dos fluxos de trabalho básicos para que, em geral, cada um possa fazer tudo o que o outro faz (embora possivelmente de uma maneira menos conveniente). Por exemplo, existem maneiras de congelar versões exatas de uma configuração de construção válida e de resolver dependências com um estado antigo de Hackage com cabal-install, e é possível exigir dependências não-Stackage ou substituir versões do pacote de instantâneo ao usar a pilha .
Por último, outra diferença entre cabal-install e stack que é grande o suficiente para valer a pena mencionar nesta visão geral é que o objetivo da stack é fornecer um ambiente de construção completo, com recursos como gerenciamento automático de instalação GHC e integração Docker . Em contraste, cabal-install deve ser ortogonal a outras partes do ecossistema e, portanto, não tenta fornecer esse tipo de recurso (em particular, as versões do GHC devem ser instaladas e gerenciadas separadamente, seja por meio da distribuição Linux pacotes, o Haskell Platform Core no Windows ou a ferramenta ghcup ).
fonte
Pelo que pude ver no FAQ, parece que Stack usa a biblioteca Cabal, mas não a
cabal.exe
binária (mais corretamente conhecida como cabal-install). Parece que o objetivo do projeto é o sandbox automático e evitar o inferno da dependência.Em outras palavras, ele usa a mesma estrutura de pacote Cabal, apenas fornece um front-end diferente para gerenciar essas coisas. (Eu acho que!)
fonte
cabal
, seu código-fonte parece estar usandodocker
. Embora eu não saiba se eles usam isso ainda.