Haskell · Cabal · herramientas de compilación
Los sandboxes de Cabal: qué fueron y qué los reemplazó
cabal sandbox es ya histórico — si solo quieres el flujo de trabajo moderno, salta a qué usar hoy.Cuando cabal sandbox llegó en cabal-install 1.18 en agosto de 2013, arregló lo más doloroso del desarrollo en Haskell de entonces: la base de datos global de paquetes. Antes de los sandboxes, cada cabal install escribía en un único almacén compartido ~/.cabal. Instala dos proyectos que necesitaran versiones distintas de la misma biblioteca y te topabas con el infame "infierno de las dependencias" — una base de datos global corrupta que a menudo terminaba con rm -rf ~/.ghc ~/.cabal y empezar de cero.
Los sandboxes hicieron que las dependencias fueran por proyecto. Ese principio nunca desapareció — pero el mecanismo sí. Aquí tienes el panorama completo, desde cómo funcionaban los sandboxes hasta el flujo de trabajo al estilo Nix que los reemplazó.
Qué era realmente un sandbox
Un sandbox era una base de datos de paquetes local al proyecto. Creabas uno en el directorio de tu proyecto:
$ cd my-project
$ cabal sandbox init
Writing a default package environment file to
/home/you/my-project/cabal.sandbox.config
Creating a new sandbox at
/home/you/my-project/.cabal-sandbox A partir de ahí, cabal install y cabal build ejecutados dentro de ese directorio usaban .cabal-sandbox/ en lugar del almacén global. Dos proyectos podían depender de versiones en conflicto de aeson o text sin interferir nunca, porque cada uno tenía su propia base de datos aislada.
Dependencias de fuentes locales
La otra característica genuinamente útil era add-source, que permitía a un sandbox incorporar una biblioteca directamente desde una copia local — algo inestimable cuando trabajas a la vez en una biblioteca y en una aplicación:
$ cabal sandbox add-source ../my-library
$ cabal install --dependencies-only
$ cabal build Editabas ../my-library, recompilabas la aplicación y cabal detectaba el cambio y recompilaba la dependencia. Esto era lo más parecido a un flujo de trabajo de monorepo que tenía Haskell en 2013.
Por qué los sandboxes acabaron retirándose
Los sandboxes resolvían el aislamiento pero dejaban dos problemas sin resolver:
- Sin compartición entre proyectos. Cada sandbox recompilaba el mundo desde cero. Diez proyectos que dependieran de
lenssignificaban diez builds separadas delensy su enorme árbol de dependencias — lento y voraz en disco. - Sin reproducibilidad entre máquinas. Un sandbox capturaba dónde vivían los paquetes, no un plan preciso y repetible de qué versiones exactas se elegirían. Dos desarrolladores ejecutando los mismos comandos con una semana de diferencia podían aun así obtener builds distintas.
La solución, tomada conceptualmente de Nix, fue hacer que las builds fueran direccionadas por contenido y compartidas globalmente: compilar cualquier combinación dada de paquete-versión-más-flags una vez, almacenarla bajo un hash en un almacén global inmutable y dejar que cada proyecto que necesite esa combinación exacta la reutilice. Eso son las "builds locales al estilo Nix", y llegaron como new-build en Cabal 2.0.
Qué usar hoy (2026)
cabal sandbox quedó obsoleto durante la serie Cabal 2.x y se eliminó por completo en versiones posteriores. El flujo de trabajo moderno y predeterminado del cabal-install actual no necesita ningún paso de inicialización — el aislamiento es automático:
# In any project directory with a .cabal file:
$ cabal build # nix-style local build (v2 is the default now)
$ cabal run
$ cabal repl
$ cabal test Lo que ocurre por debajo es exactamente el aislamiento por proyecto que los sandboxes prometían, más la compartición que les faltaba:
- Los artefactos de build de tu proyecto van en un directorio local
dist-newstyle/(el sucesor espiritual de.cabal-sandbox/). - Las dependencias compiladas van en un almacén global inmutable (
~/.cabal/store, o bajo~/.local/state/cabalen las disposiciones más nuevas), indexadas por un hash del paquete, la versión, las dependencias y los flags. Compilalensuna vez; cada proyecto que reutilice el mismo plan enlaza la misma entrada del almacén. - Un archivo
cabal.projectreemplaza acabal.sandbox.configpara la configuración, las builds multi-paquete y el pinning.
El equivalente moderno de add-source
Las dependencias de fuentes locales y remotas viven ahora en cabal.project:
# cabal.project
packages: . ../my-library
-- or pull a dependency straight from git:
source-repository-package
type: git
location: https://github.com/owner/some-lib
tag: 0a1b2c3d Esto es estrictamente más potente que add-source: maneja múltiples paquetes locales, pins exactos de git y builds reproducibles multi-repo.
Fijar versiones de forma reproducible
Para la reproducibilidad que los sandboxes nunca ofrecieron, genera un archivo freeze que bloquee cada versión transitiva:
$ cabal freeze # writes cabal.project.freeze
# commit it — every machine now resolves the identical plan ¿Y qué hay de Stack?
Stack aborda los mismos objetivos desde otro ángulo: en lugar de resolver versiones por proyecto, compila contra snapshots curados (resolvers de Stackage como lts-22.x) donde se sabe que un conjunto entero de paquetes compila junto, y comparte las builds globalmente por snapshot. Ambas herramientas están sanas y muy usadas en 2026; la división práctica es a grandes rasgos "quiero el toolchain estándar y un control fino" (Cabal) frente a "quiero un conjunto curado y de confianza listo para usar" (Stack). Ninguna usa sandboxes — el concepto está totalmente superado en ambos lados.
Chuleta de migración
cabal sandbox init → (nothing — just `cabal build`)
cabal sandbox add-source ../lib → packages: . ../lib (in cabal.project)
cabal install --dependencies-only → cabal build --only-dependencies
.cabal-sandbox/ → dist-newstyle/ (local) + ~/.cabal/store (shared)
cabal.sandbox.config → cabal.project (+ cabal.project.freeze) La lección que enseñaron los sandboxes — nunca contaminar un estado mutable global, aislar por proyecto — triunfó tan por completo que ahora es invisible: es simplemente cómo se comporta cabal build. Si estás leyendo esto porque un enlace o tutorial antiguo te apuntó a cabal sandbox init, puedes olvidarte tranquilamente del comando. Solo cabal build.