I have a very minimal nix.configuration, write very small shell.nix files, and try to only use things I know or understand. So I’m definitely only using 1% of Nix right now but I’m comfortable with it!
Edit: I should clarify Nix is the build tool at work for Haskell and some of my colleagues are contributors so I know I can get help if stuck. I’m a noob though.
I use nix in production, and I love it. It's just as good in practice as it is in theory.
I think the problem is that really using nix involves learning a new language. And it's a weird lazy functional language at that. So yeah, the Haskell folk adopt it readily enough, but everyone else has a high barrier to get over. The only people that do it are the ones that have really wrestled with the problem of dependencies and can see how well nix solves it.
I could not agree with you more! I use nix daily, and every time I go to edit it a nix file a voice in the back of my head says, "you should really start that Haskell to Nix compiler you've been thinking about."
[edit] ha! just notice the next comment talking about hnix. Great minds... :)
Well, I don't know the details of your personal experience, but I'm confident to declare that the vast majority of the Haskell community has never used Nix and has no particular intention to.
I have been avoiding nix for a while since I had a bad time with it several years ago, however recently used it for a small Haskell/Latex environment for literal programming and found it worked really well. I’m probably going to invest time into learning it now, as the online docs seem to have gotten better.
I use Nix and it's awesome, but still in early adopter territory. It works wonderfully if you really value reproducible builds and are willing to put some effort in the initial setup, but it's still a bit fiddly and documentation is nearly non-existent. If you have the time and motivation to learn about it up-front and get it set up it pays off, but I wouldn't recommend it to beginners just trying to learn Haskell.
Nix is basically merely a quirky functional programming language that generates shell scripts to be run in a sandbox for the actual build. It is not a great tool for within-a-project building; its minimal unit of work has a pretty high overhead.
I guess my experience is colored by my last gig as a Haskell developer, where our entire development and deployment process was nix-based.
I understand that it is possible to use Haskell without using Nix. However, I do get the impression that a significant section of the community see nix as the best way to manage Haskell dependencies. The (insanely confusing) naming of the new cabal features seems to support that.
Aside from perhaps the syntax of the Nix declarations (which isn't Haskell, though it is lazy etc.), is there anything holding you back from using Nix? As an alternative, are you familiar with Guix?
I love nix and have contributed quite a few packages to the nix repository, and I will vouch that it’s anything but easy. I have a background in Haskell which makes it more familiar, but even the syntax is counterintuitive to newcomers.
This is why I manage every nontrivial project I do nowadays with Nix (Haskell, Go, Python, C & C++, bash ..anything)
Everything is pinned to exact source revisions. You can be relatively sure to be able to git clone and nix-shell and be off to the races.
You can even go the extra mile and provide working editor integration in your nix-shell (especially easy with emacs). So you can enable anyone to git clone, nix-shell, and open a working editor.
The biggest downside is becoming proficient in Nix isn't easy or even straightforward.
I totally get that sentiment about nix, and actually I sort of share a variation of it too: I really want to learn it, and I like the featureset in theory, but I can't get used to it in practice, and I don't have the time to invest myself into something that difficult to get going.
The reason I brought up the nix command is that I only use nix, for haskell development, for that specific command: I found it once in a blog post, saved it, then put it under a function into my bashrc, and I use nix quite literally for only that purpose. I've done a lot of development on various functional languages (with a dayjob in F# that lasted 3 years) and being able to quickly experiment with libraries was something that I sorely missed when doing repl experimentation in those languages (I think F# recently got a #nuget directive, but that was after I stopped using it).
I've tried this out a few days ago. I have some basic theoretical Haskell knowledge, but not much practical experience. However I do have some significant Nix experience.
Ended up not even going through the beginner tutorial, as the installer/scaffold process required me to do things that I didn't like:
- forced scaffolding of projects with some quite blackboxy generated shell scripts inside
- use of nix, yet requiring me to install 'make' and 'direnv' system-wide (why? just let me use a shell.nix)
- required me to use cachix.org as a system-wide nix substituter, which I don't want to do for security reasons (just allow me to build everything myself)
All in all this looked promising, but ended up being too magical for my taste. I'd like to be able to start using IHP 'from scratch' instead - with my own Cabal/Nix/Bazel build machinery. This is a critical requirement for libraries/frameworks that I use.
Your mileage may vary though - if you're okay with RoR-like scaffolding and blackboxness, then you might feel at home here, and at least you get a nicely typed language in return.
I, too, have no desire to put so much work into having a working system (but I guess, there’s no way around nix for me, if I want to use haskell and ghcjs). Unfortunately from my own recent personal experience it does indeed have a steep learning curve .
I really like the general idea of nix, I think it’s going in the right direction and I am very grateful for all the people doing amazing work there and I wanted to give it a try for a long time, now.
But my recent experience with nix on MacOs has mostly just been incredibly frustrating. I started using nix one or two weeks ago, because I needed it for a project with haskell-miso (which I very much like, by the way).
As long as I just stuck to using the default.nix provided by Miso, everything worked fine, more or less, but as soon as I tried to go beyond that to customize things for the needs of my own project, the problems started to accumulate.
I needed to google for and apply manual fixes for some very basic things, because nix did not play well with neither macOS Catalina (nix needs access to /nix) nor with fish.
Some haskell packages I need like constructible were broken in the default channel and I had no idea how to fix those packages. In the end I ended up switching to a “stable” version. I do not understand why nixpgs-unstable is the default channel, by the way.
Sometimes things seem easy in some guides and I thought I understood them, but then when I tried them they just won’t work. For example I was hoping that
nix-shell -p 'haskell.packages.ghcjs.ghcWithPackages (pkgs: with pkgs; [ miso ])’
would give me a shell with the ghcjs compiler and the package miso, but that resulted in an error (after waiting for the result for quite some time and a lot of text scrolling by).
I tried following guides and didn’t try to do anything especially crazy, but somehow I ended up fucking up my haskell build environment so much, that I couldn’t do anything Haskell-related anymore. Still don’t how I managed to do that.
I tried rolling things back through
nix-env -G 1
but that didn’t work. Somehow the only think that helped me was deleting everything nix-related and trying again. I then switched away from the unstable channel in the very beginning and now things seem to somewhat work, more or less.
When I was 15 years younger I really enjoyed playing around with the configuration of my computer, trying different window managers and editors etc., but nowadays I have work I care about and limited time and I want my computer to just work and not get in the way. Nix really, really got in the way. It’s been incredibly frustrating the last few days, when I wanted to work on my project, but spent several days fighting with nix instead.
Sorry for the rant, again, I very much like the project and I really hope it succeeds, I just wanted to share my own experience with it, as a beginner.
Haskell is the only language where you seem to need Nix. That alone make a big difference for people trying to get into Haskell. I'd say it's also the only language where you seem to need dev-infra tooling. I can see how using Nix helps, but saying that "it's already solved on other level of dev-infra tooling" is basically a way to confirm "This language has some of the worst tooling I've ever encountered in my life.", which was the initial assertion.
Perhaps in contrast to most people's experiences, I haven't found Nix hard to learn. I think it really helps if you have learned Haskell before. Nix (the language) is really a simple functional programming language, but Nix relies quite heavily on functional programming concepts like laziness, fixed points, etc. A lot of things are underdocumented, but if you understand the Nix language well, it isn't hard to look up definitions in nixpkgs. I can understand that it is all very alien and overwhelming if you do not have a grounding in functional programming.
The primary issue for me has been that Nix is a very deep rabbit hole. You can spend enormous amounts of time on making your configuration more functional and declarative. Pretty much like you can spend enormous amounts of time on customizing an Emacs configuration. It's hard to strike a balance. And outside declaratively defined infrastructure (servers), it's probably not really worth it. I could almost fully reproduce my NixOS system (there is always some mutable state left) with a single command. But takes many months of effort to get to that point. On the other hand, I can set up a fresh macOS or Fedora Silverblue systems with all my customizations in 1 or 2 hours and have to do that maybe once of twice a year? So, ¯\_(?)_/¯.
I think the balance is different when you manage a lot of servers and most servers can be defined as a function with a small number of varying parameters.
The other part of the rabbit hole is that software breaks frequently in Nix. Upstreams do not really develop things under the assumption of a non-FHS, immutable system. So, you were going to work on something, but before you know it is 30 minutes later because you ended up fixing some package you need and that broke. Similarly, you'll end up packaging a lot of stuff and spending quite some time making it fit the Nix mold (looking at you Python packages that mutate in-place, sigh).
I love Nix as a principle -- it's declarative, immutable, pure, reproducible. But in practice, you can reap many of the same benefits from impure, inferior alternatives, with far less work. Yes, Docker is an ugly duck compared to Nix, but it brings 90% of the reproducibility benefits and probably everyone on your team can be up and running in hours. Rust's cargo doesn't allow you to specify every non-Rust dependency exactly, but with a Cargo.lock file you can make most of your build reproducible. NixOS is a clean, immutable, declarative system, but other systems offer a subset of its features, such as atomic upgrades/rollbacks, immutable root, and isolated applications (e.g. Fedora SilverBlue + Flatpaks, Fedora IoT, macOS). These alternatives are far more familiar and easier to work with. You can get most (but not all) of the benefits of NixOS with far less work.
Edit: I should clarify Nix is the build tool at work for Haskell and some of my colleagues are contributors so I know I can get help if stuck. I’m a noob though.
reply