haskell / haskell/cabal

[RFC] Revive cabal sandboxes (UX)

Open
#10,098 17 comments 8 reactions 0 assignees View on GitHub
re: v1-vs-v2 type: enhancement type: RFC
Dominant language
Haskell
Stars
1.7k
Forks
750
Avg merge
4d 3h
Merged PRs (30d)
28

Description

## Motivation

At ZuriHac 2024 we (@andreabedini, myself and others) talked with @ivanperez-keera and @fdedden about the user experience of using GHC and cabal for people who are not Haskell developers and are not interested in Haskell on its own, but rather use it to:

- build a package
- use a framework/library that requires Haskell (e.g. copilot)

These users are **not** interested in:

- nix
- Haskell
- cabal
- content addressable storage
- declarative environment configuration

The `cabal v2` commands are assuming a lot of these things UX-wise.

We are well aware that there are ways to utilize store location and environment files to achieve something similar. But this misses a consistent UX experience.

## Imperative workflow

We propose here an imperative workflow of managing haskell packages.

1. the user asks cabal to `install` a package
2. cabal makes this package visible to
- ghc/ghci
- cabal itself
3. building a project (and similar operations) will re-use the already installed packages

This follows the workflow of 90% of Linux distributions. It usually disallows having multiple versions of the same library.

## A sandbox workflow

The sandbox workflow is an extension of the imperative workflow. A sandbox is scoped to a specific directory (and its subdirectories). Installing packages inside the sandbox only makes them available within that directory. A sandbox can be conveniently created and conveniently destroyed. A user would rather destroy a sandbox and start from scratch rather than try to fix it. This is outlined in the following workflow:

1. user clones e.g. copilot
2. user creates a sandbox inside the copilot repo
3. user installs the necessary Haskell libraries and the copilot library
4. user uses a Makefile to link to copilot and other libraries (compare with [bluespec](https://github.com/B-Lang-org/bsc/blob/9a97f9d037c462e42441b6af8d0000314302214f/src/Makefile#L29), which does the same)
5. user upgrades the project
6. user destroys the sandbox
7. repeats from step 2

A similar workflow can be imagined with an actual cabal package that is developed ad-hoc iteratively.

Users who want maximum caching and declarative configuration can use the existing -v2 interface instead.

## Implementation details

We have considered the following:

1. utilize -v1 to implement sandboxes (probably similar to the old implementation)
2. utilize -v2 to implement sandboxes

### v2 based sandbox implementation

A possible implementation would be:

1. `cabal sandbox init` would e.g. augment `cabal.project.local` with several configurations
- `write-ghc-environment-files: always`
- `store-dir: .cabal-sandbox` (this doesn't seem to be supported yet through the cabal project file)
- `package-env: .` (seems to be not supported either through cabal project file)
2. `cabal install` would then
- use the sandbox store dir
- use the current dir as package env and write the configuration file
- also add `constraints: installed` to `cabal.project.local`
3. `cabal sandbox destroy` would
- delete the `.cabal-sandbox` directory
- delete the ghc environment file
- delete `cabal.project.local`

This would ensure consistency between directly invoking ghc and using cabal to actually build packages.

It would also allow to move the created constraints to `cabal.project` file instead (for committing them to git). We could also imagine slight variants of this idea where we utilize yet another project file with a different suffix if `cabal.project.local` is deemed inappropriate.

### Alternative v2 implementation without utilizing cabal.project files

An alternative implementation could create a sandbox config file that then triggers sandbox behavior in cabal (through cabal checking for its existence). This is partly implemented here: https://github.com/hasufell/cabal/pull/3
But I consider it more controversial. However **it is more opaque**.

## Related discussions and prior art

* https://github.com/haskell/cabal/issues/9581
* https://github.com/haskell/cabal/issues/6481

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.