Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command to add a dependency to the project #5429

Open
4 tasks
ChrisPenner opened this issue Nov 12, 2020 · 2 comments
Open
4 tasks

Command to add a dependency to the project #5429

ChrisPenner opened this issue Nov 12, 2020 · 2 comments

Comments

@ChrisPenner
Copy link

ChrisPenner commented Nov 12, 2020

Preamble

Hey folks! Thanks for all the amazing work you've done making Haskell builds approachable! The community really appreciates it, and benefits from your work every day!

Lately I've been looking around for ways to make Haskell more approachable for beginners and a sticking point for some going from their first "Hello, World!" using only the Prelude to adding their first dependencies, which tends to happen much earlier in Haskell than in other languages. You can develop entire apps in Javascript, python, and go, without taking on dependencies if you wish, but in Haskell you need a "containers" dependency to use even a simple key-value map, so it's likely people will hit this barrier pretty early on.

I propose a command for adding dependencies to your project in a quick & easy fashion:

stack add <package>

I see that this was discussed in #115, however it appears that the "stack.yaml" update commands were addressed and the package commands were of lesser priority, the comment at the end says to leave further updates to their own issues, so this is me doing that 😄
I searched through issues as best I could, but couldn't find an existing issue for this, so please let me know if I've duplicated anything.

Motivation

I believe this feature's primary benefit will be to act as an easy way for beginners to add dependencies without worrying about any of the underlying complexities inherent to building a Haskell project. Empowering beginners in this way helps them have a good first experience in the language and improves their perception of the language overall.

There are currently several barriers to adding a first dependency which beginners will encounter. Some of the first will be:

  • What's the difference between stack.yaml & package.yaml
  • Which do I use for what
  • Why does installing some packages involve modifying both?

There are good answers to each of these questions of course, but I'd argue they're not questions that need to be front-of-mind for a brand new Haskeller, they should be able to put these off until later on, but unfortunately, in order to add a simple "containers" dependency they'll need to work through them to figure out where to put it.

There's unfortunately a very large potential foot-gun in the shape of stack install <my-package>. Every other dependency manager out there has some variant of this, which adds a dependency on <my-package>, and given the popularity of npm install, bundler install and pip install, it's VERY likely that new users will try this. Unfortunately, running stack install containers will actually SUCCEED, but will do absolutely nothing to help the user, who is bewildered that this command is running "successfully" but is not affecting their project in the slightest.

When the user eventually finds a stack-overflow explaining this to them, they now know they must edit a configuration file manually, and they set off on the quest to determine how to do so. Thus begins the next set of questions the enterprising new beginner will ask themselves:

  • I seem to have a package.yaml AND an app.cabal, they seem to be similar, and some tutorials say to edit one, some say to edit the other. Where do I make my change?
  • I edited my app.cabal and now stack seems to be mad at me. What did I do wrong and how do I fix it?
  • I'm looking at package.yaml and there seem to be many different places to add a package, where do I need to put it? (dependencies, library.dependencies, executable.dependencies, tests.dependencies)
  • I see that the dependency that's already there has a version requirement on it (e.g. base >= 4.7 && < 5), do I need a version requirement for containers for it to work?

Again, these are all confusing and annoying questions for beginners that they really shouldn't need to worry about right now, they're likely pretty far from publishing their own library at this point, so we really just need to help them get the packages they need installed without too much trouble, even if we make some assumptions as a result. They don't need version constraints since LTS's will handle that for them, but they won't know that and might stress about it, or even will specify INCORRECT constraints and prevent their project from building and get even more frustrated.

Other benefits include:

  • Haskell tutorials don't need to laboriously explain the process of installing packages, they can simply provide a command to copy-paste
  • Scripts and automations are much easier for devs to write, they don't need to take on yaml dependencies and know anything about the contents of the current snapshot and whether they'll need to adjust extra-deps
  • Running a single command which you likely have in your shell history is much faster than opening a yaml, finding the correct location, adding the package, running stack build, then copy-pasting the extra-dep into stack.yaml.

Goals

Here are the goals of this issue, how exactly they are attained is open for constructive debate:

  • As a beginner I can run a single, simple command to add a dependency to my stack project without editing any files (regardless of whether the package is in the selected LTS)
  • If I try to compile my project, but I'm missing a dependency, stack will provide a command I can run to solve the problem

The following I would consider "nice-to-have" since they'd help more advanced users to use the feature more precisely:

  • The ability to specify a package version
  • The ability to specify that this is a (test|lib|exe|common) dependency

I know that stack has largely avoided working with cabal/package.yaml files in the past, but for better or worsse, stack is seen by beginners to be Haskell's build-system & package manager and the user experience suggests it should likely be able to perform these tasks.

If we can reach a consensus, and someone can point me in the right direction, it's likely I can implement the features myself (though if someone else is willing to do so I'd be more than thankful 😄 )

Thanks everyone!

@ChrisPenner
Copy link
Author

Upon further investigation I see this is a duplicate of #1933 ; but seeing as it was created 2 years ago and hasn't had much further conversation it's likely worth bringing up again.

Although not explicitly mentioned in the other issue, it seems one of the blockers was the idea of preserving comments in the stack.yaml file; I'd argue that while this would be very nice to have, it shouldn't be a blocker for getting this through, as the comments are largely provided to help users manually edit the file, whereas this feature's goal is to prevents the need to manually edit the file in most cases, so the comments likely won't matter as much.

Other concerns appear to be version bounds, my suggestion on this is to not let bike-shedding over the "best" version bounds get in the way here; I think adding the package without any version bounds is perfectly acceptable as a starting point. Additional option flags can of course be added in the future, but given the existence of snapshots, version bounds are largely irrelevant to beginners, and even intermediate users up until the point of publishing their own apps/libraries, at which point they can likely learn to update the files by hand 👍

@philderbeast
Copy link
Contributor

it seems one of the blockers was the idea of preserving comments in the stack.yaml file

@ChrisPenner #5813 preserves comments in YAML updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants