Qual é a diferença entre Cabal e Stack?

104

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?

ZhekaKozlov
fonte
fpcomplete.com/blog/2015/06/announcing-first-public-beta-stack (em suma, meio que substitui cabal-installe 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)
Carsten
A pilha AFAIU é útil para trabalhar rapidamente em um projeto existente. Se você começar algo do zero, certamente terá que usar a cabala.
mb14
@ mb14 Não é o caso. Você pode usar a pilha para iniciar projetos do zero. Na verdade, os modelos de pilha fornecem uma maneira fácil de fazer isso.
Sibi,
Veja este breve artigo para uma boa visão geral: scs.stanford.edu/16wi-cs240h/labs/stack.html
michid

Respostas:

76

A pilha é um substituto para o Cabal?

Sim e não.

Em quais casos devo usar Stack em vez de Cabal? O que Stack pode fazer que Cabal não pode?

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:

  • O Stack até baixa GHC para você e o mantém em um local isolado.
  • Suporte Docker (que é muito conveniente para implantar seus aplicativos Haskell)
  • Script Haskell reproduzível : você pode identificar a versão de um pacote e pode ter a garantia de que ele sempre será executado sem nenhum problema. ( Cabal também tem um recurso de script , mas garantir totalmente a reprodutibilidade com ele não é tão simples.)
  • Capacidade de fazer stack build --fast --file-watch. Isso será reconstruído automaticamente se você alterar os arquivos locais presentes. Usá-lo junto com a --pedanticopção é um obstáculo para mim.
  • Stack oferece suporte à criação de projetos usando modelos . Ele também suporta seus próprios modelos personalizados.
  • Stack tem suporte embutido para hpack . Ele fornece uma forma alternativa (IMO, a melhor) de escrever arquivos cabal usando o arquivo yaml, que é mais amplamente usado na indústria.
  • Intero tem uma experiência tranquila ao trabalhar com Stack .

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.

Sibi
fonte
Houve alguma mudança desde que cabal 3 foi lançado?
William Rusnack
1
@WilliamRusnack Sim, tem. Primeiramente, o fluxo de trabalho padrão do Cabal agora incorpora prevenção de conflito de dependência, embora a estratégia que ele usa para fazer isso seja visivelmente diferente da de Stack. (@Sibi: Tomei a liberdade de atualizar sua resposta para que reflita melhor onde as coisas estão atualmente.)
duplode
35

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 .cabalarquivo 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 resolvercampo de stack.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..cabalproject.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 ).

duplode
fonte
11

Pelo que pude ver no FAQ, parece que Stack usa a biblioteca Cabal, mas não a cabal.exebiná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!)

Orquídea Matemática
fonte
Além de cabal, seu código-fonte parece estar usando docker. Embora eu não saiba se eles usam isso ainda.
Sibi
@Sibi Sim, parece que você pode, opcionalmente, jogar coisas no Docker, e isso deve funcionar. Eu não olhei muito mais longe ...
Orquídea Matemática