It's not the functional nature of Nix that is hard to deal with. Nix's functional nature is actually its saving grace.
My difficulty with Nix is that there are important subjects that aren't taught.
I figured out how to create a usable `default.nix` and `shell.nix`, but that takes a lot of effort, and there really aren't many resources to reference.
Nix expressions use a lot of predefined functions, and I have no idea where their documentation exists, if it does at all.
Even if there is some explanation for all of the functions that I need to use, there isn't documentation for how to fit them together.
Instead of being in dependency hell on the outset (like most package managers), I find myself in dependency hell when I want to do something different. The Nix community has an irrational hatred of version numbers, meaning you have to scour the web for a derivation that gets the right version of a dependency, and "pin" it, or hope that the channel you are using has the correct version. Even when channels do have the version you want, sometimes that channel provides multiple package versions, some with the version in the name.
Names are a mess. Since every package must exist in the same namespace, but its derivation is helpfully sorted into a directory tree, the same packages will often have different names. There isn't a good way to search or browse for them either. I end up digging through github quite often, which is a lot more often than the never that I should find myself doing so.
Nix is wonderful. NixOS is by far my favorite OS, and that is why I deal with all of the rough edges, but they certainly are rough.
Package definitions can often be generated automatically with importers. For example, `guix import cran -r recipes` creates package definitions for the recipes package and all its R dependencies. They usually work with minimal adjustments.
Jumping to package definitions is easy thanks to REPL support (e.g. with Emacs + Geiser), but you can also use `guix edit name` and it will spawn an editor to edit the package "name".
Creating variants of packages is trivial as package definitions can inherit from existing definitions. I maintain a bunch of different versions for bioinformatics tools. I can select them on the command line simply by appending the version string, e.g. "samtools@0.1".
Guix has a comprehensive manual with a procedure and variable reference and examples.
I really like Guix and GuixSD because of how consistent and hackable it is.
Also, this popped on twitter https://github.com/Gabriel439/slides/blob/master/nix-interna...
The problem with derivations is that they are like a library without a reference
The functions that are to be used in derivations aren't documented clearly, at all, or in an obvious place.