1. 4

    Hi, I’m Vaibhav and I write about functional programming (especially with Haskell and Nix) and automation.

    Link: https://vaibhavsagar.com

    1. 41

      It’s also developer-friendly because of its excellent wiki.

      I learned Linux doing everything by hand on a Slackware system, then moved to Ubuntu after ~8 years when I realized I’d stopped learning new things. Then a couple years ago I realized I didn’t understand how a bunch of things worked anymore (systemd, pulseaudio, Xorg, more). I looked at various distros and went with Arch because its wiki had helped me almost every time I’d had an issue.

      Speaking of distros, I’m currently learning Nix and NixOS. It’s very nice so far. If I can learn to build packages I’ll probably replace lobsters-ansible with it (the recent issues/PRs/commits tell a tale of my escalating frustration at design limitations). Maybe also my personal laptop: I can experiment first with using nix to try xmonad first because it’s mostly configured by editing + recompiling) and deal with python packaging, which has never worked for me, then move completely to NixOS if that goes well.

      1. 9

        I switched from Mac to NixOS and couldn’t be happier. At work we use Nix for building Haskell projects as well.

        1. 9

          The Arch wiki actually seems to be the only good documentation for using the advanced functionality of newer freedesktop components like pulseaudio, or much older software like Xorg.

          But I’ve noticed it’s documentation for enterprise software like ZFS is usually hot garbage. Not surprising given the community. The recommendations are frequently hokey nonsense: imaginary micro-optimizations or blatantly incorrect feature descriptions.

          What do you find better about nix for making packages than, say, making an rpm or deb? I’ve found those package systems valuable for large scale application deployment. Capistrano has also been nice for smaller scale, with its ability to deploy directly from a repo and roll back deployments with a simple symlink swap. And integration libraries are usually small enough that I’m comfortable just importing the source into my project and customizing them, which relieves so many minor tooling frustrations overall.

          Of course in the end the best deployment system is the one you’ll actually use, so if you’re excited about packaging and deploying with nix, and will thus devote more time and energy to getting it just right, then that’s de facto the best option.

          1. 3

            What do you find better about nix for making packages than, say, making an rpm or deb?

            I don’t, yet. The “If I can learn to build packages” sentence links to an issue I’ve filed. I was unable to learn how to do so from the official documentation. I’ve almost exclusively been working in languages (PHP, Python, Ruby, JavaScript) that rpm/deb have not had good support for, prompting those languages to each implement their own package management systems that interface poorly or not at all with system packaging.

            I’ve used Capistrano, Chef, Puppet, and currently use Ansible for deployment. Capistrano and Ansible at least try to be small and don’t have a pretensions to being something other than an imperative scripting tool, but I’ve seen all of them break servers on deployment, let servers drift out of sync with the config, or fail to be able to produce new deployments that match the existing one. Nix/NixOS/NixOps approach the problem from a different direction; it looks like they started from what the idea of system configuration is instead of scripting the manual steps of maintaining one. Unfortunately nix replicates the misfeature of templating config files and providing its own config file on top of them instead of checking complete config files into a repo. Hopefully this won’t be too bad in practice, though it’s not a good sign that they implemented a programming language.

            I appreciate your closing sentiment, but I’m not really trying to reach new heights of system configuration. I’m trying to avoid losing time to misconfiguration caused by services that fundamentally misunderstand the problem, leading to booby traps in common usage. I see almost all of my experience with packaging + deployment tools as a loss to be minimized in the hopes that they waste less time than hand-managing the global variables of public mutable state that is a running server.

            1. 1

              Hmmm. I don’t think the problems you listed are 100% avoidable with any tool, just easier in some rather than others.

              I like Puppet and Capistrano well enough. But I also think packaging a Rails application as a pre-built system package is definitely the way to go, with all gems installed and assets compiled at build time. That at least makes the app deployment reproducible, though it does nothing for things like database migrations.

            2. 1

              What do you find better about nix for making packages than, say, making an rpm or deb?

              Let me show you a minimal nix package:

              pkgs.writeScriptBin "greeter" "echo Hello $1!"
              

              Et voila! You have a fine nix package of a utility called greeter that you can let other nix packages depend on, install to your environment as a user or make available in nix-shell. Here’s a function that returns a package:

              greeting: pkgs.writeScriptBin "greeter" "echo ${greeting} $1!"
              

              What you have here is a lambda expression, that accepts something that you can splice into a string and returns a package! Nix packages in nixpkgs are typically functions, and they offer an a great amount of customizability without much effort (for both the author and the user).

              At work, we build, package and deploy with nix (on the cloud and on premises), and we probably have ~1000 nix packages of our own. Nobody is counting though, since writing packages doesn’t feel like a thing you do with nix. Do you count the number of curly braces in your code, for instance? If you’re used to purely functional programming, nix is very natural and expressive. So much so that you could actually write your application in the language if it’s IO system were designed for it.

              It also helps a lot that nix can seamlessly be installed on any Linux distro (and macOS) without getting in the way of its host.

              1. 1

                If only ZFS from Oracle hadn’t had the licensing compatibility issues it currently has, it would probably have landed in the kernel by now. Subsequently, the usage would have been higher and so would the quality of the community documentation.

              2. 4

                If I can learn to build packages I’ll probably replace lobsters-ansible with it

                Exactly. I don’t have much experience with Nix (none, actually). But in theory it seems like it can be a really nice OS-level replacement for tools like Ansible, SaltStack, etc.

                1. 1

                  This is exactly what NixOps does! See here.

                  1. 2

                    Thanks for the video. I’ll watch it over the weekend!

                    Curious - are you also running NixOS on your personal machine(s)? I’ve been running Arch for a long time now but considering switching to Nix just because it makes so much more sense. But the Arch documentation and the amount of packages available (if you count the AUR in) is something that’s difficult to leave.

                    1. 1

                      Yes, I’m using it on my personal machine :). I wouldn’t recommend switching to NixOS all at once, what worked for me was to install the Nix package manager, use it for package management and creating development environments, and then only switch once I was fully convinced that NixOS could do everything I wanted from my Ubuntu install. This took me about a year, even with me using it for everything at work. Another approach would be to get a separate laptop and put NixOS on that to see how you like it.

                      1. 1

                        Interesting. I’ll try it out for some time on a VM to get a hang of it. Thanks for the info!

                2. 3

                  Even as a Ubuntu user, I’ve frequently found the detailed documentation on the Arch wiki really helpful.

                  1. 2

                    I really want to use Nix but I tried installing it last month and it doesn’t seem to have great support for Wayland yet which is a deal breaker for me as I use multiple HiDPI screens and Wayland makes that experience much better. Anyone managed to get Nix working with Wayland?

                    1. 2

                      Arch’s wiki explaining how to do everything piecemeal really seems strange given its philosophy is assuming their users should be able to meaningfully help fix whatever problems cause their system to self-destruct on upgrade. It’s obviously appreciated, but still…confusing, given how many Arch users I’ve met who know nothing about their system except what the wiki’s told them.

                      1. 1

                        I gave up on my nix experiment, too much of it is un- or under-documented. And I’m sorry I derailed this Arch discussion.

                        1. 1

                          I’m happy to help if I can! I’m on the DevOps team at work, where use it extensively, and I did a presentation demonstrating usage at linux.conf.au this year. All my Linux laptops run NixOS and I’m very happy with it as an operating system. My configuration lives here.

                          1. 2

                            Ah, howdy again. I’m working my way through the “pills” documentation to figure out what’s missing from the nix manual. If you have a small, complete example of how to build a single package that’d probably be pretty useful to link from the github issue.

                            1. 2

                              I made a small change to the example to get it to build, and I’ve added it as a comment to your issue.

                        1. 7

                          I use NixOS as my main OS at home and I think it’s the best thing I’ve done for having a stable system. I was mucking around with some boot deps and messed something up and all I had to do to get back to a working system was choose one option up at the grub menu and I booted into my system as it was before I had made the change.

                          However there’s a few things that I wish were better:

                          You pretty much need to put your nixos config into version control. While you can revert to a previous version of your system, it doesn’t actually save the previous version of your config, you need to manually revert before making any changes.

                          While versions of things are tracked explicitly and you can have multiple versions installed, nixpkgs generally doesn’t have multiple versions available to install/depend on (with the obvious exceptions of big things like py2/3). This means if you need a newer version of something and want to contribute back you have to update everything else that depends on your package’s (ie derivation’s) dependencies. That’s a pain. It also means that you can’t installed old versions of things along side new versions of things.

                          There’s also a lot to learn if you need something that’s not packaged already because there’s no way to run binaries not built explicitly for nixos. There’s not even any way to run flatpacks, snaps, or any of the others, but looking at nixpkgs there are people working on trying to make those work.

                          All that said, it’s still a better experience that any other distro I’ve used in the past. And I’ve never even tried to contribute to packages on any previous distro, so I’m not sure if it’s easier this way, but it’s a hell of a lot less intimidating for sure.

                          Also, I’m by no means an expert, take what I’ve said with a grain of salt, I’m sure there’s bound to be at least one thing I’ve said above that’s wrong just due to my inexperience.

                          And again, that’s mostly about NixOS, and not just Nix. I’m actually in the process of moving all the things I’ve installed via homebrew on my work laptop over to Nix after homebrew broke my system (twice) yet again when they mucked with the python 2/3 naming. I’m tired of dealing with it and have yet to have a serious issue with Nix on OSX. So, I can wholeheartedly suggest to everyone here to start playing around with Nix on an existing Linux or OSX system.

                          1. 5

                            It also means that you can’t installed old versions of things along side new versions of things.

                            Nothing prevents you from using different revisions of nixpkgs in different places, which would allow you to achieve this.

                            There’s also a lot to learn if you need something that’s not packaged already because there’s no way to run binaries not built explicitly for nixos.

                            This is not true, Nix has a buildFHSUserEnv function that creates a linux chroot where you can pretend you’re running a regular linux distro. @puffnfresh has a good post on using this here.

                            1. 5

                              Nothing prevents you from using different revisions of nixpkgs in different places, which would allow you to achieve this.

                              Huh, I can’t believe I never thought of that. I’ve even installed things from a local “fork” of nixpkgs and it never occurred to me that’s exactly what I was doing.

                              This is not true, Nix has a buildFHSUserEnv function that creates a linux chroot where you can pretend you’re running a regular linux distro. @puffnfresh has a good post on using this here.

                              That’s true. I guess I was inexact in what I wrote. You might not need to “package” something (as in contributing it to nixpkgs), but you still need to know enough about how things are “packaged” (as in writing any kind of derivation) so you can write a .nix file that wraps it in something that allows it to work. I really wish there was a pretend-to-not-be-nix ./rando-bin command that would handle 99% of binaries for when I just need to get something done. (Although I realize that’s asking a heck of a lot.)

                              Edit: Huh. I think that’s what you just linked. I should have read that all the way though before replying. Man, I’ve been looking for something like that for ages. I should complain about things on the internet more often.

                              1. 4

                                At work we use a few different versions of nixpkgs. We want an old version of Docker, for example. So we import the exact commit of nixpkgs we want.

                                pretend-to-not-be-nix ./rando-bin
                                

                                Is exactly what you get when using buildFHSUserEnv.

                                1. 2

                                  I really wish there was a pretend-to-not-be-nix ./rando-bin command that would handle 99% of binaries for when I just need to get something done.

                                  I think a lot of people find steam-run provides it this command in most cases!

                            1. 4

                              So far the comments I’ve shown have been personal attacks

                              Only 2 of the 6 comments up to the point this comment is made have anything personal in them. They seem to be “attacking” the concepts, not the person.

                              1. 6

                                Hi! Author here. Now that I’ve had some time to mellow, I wouldn’t call those “personal attacks”. At the time I was excited about functional pipelines (probably thanks to Elixir). No Haskell libraries provided the (|>) pipeline operator. I created Flow to fill that gap. I shared it on Reddit because I wanted to know why pipelines weren’t popular in the Haskell community. It got over 100 comments, which is huge for r/haskell. In my opinion, most of the comments were negative. They derided the library by calling it “backwards” or a “hurdle” or a “crutch” or “exactly what functional programming is trying to avoid”. I took those comments personally when I shouldn’t have.

                                These days I just import Data.Function ((&)) and wince a little every time I write (&) instead of (|>). It’s definitely not as popular as ($) and (.), but it’s hard to call it non-standard when it’s in the base package.

                                1. 2

                                  I’ve always found the “backwards” notation of & a bit odd, but as you say in your post, different notations have different uses or people who prefer them. I know haskellforall has done some stuff with & around the “make Haskell look like OOP” experiments.

                                  I mean, >>= is in this direction as the “default” so that’s not uncommon at all. I wonder if you could do some fun stuff with >>= and Identity

                                  1. 2

                                    I usually prefer (&) because it encourages iterative development. Start with some value, transform it, and keep doing that until you have the result you want. That’s how I usually work in GHCi. The alternative is to start at the “outside” and keep working in until you’re at the bottom. I find that way of developing to be better when I already have the type signature and I’m filling in typed holes.

                                    Fun fact: You can use do notation with pure computations in Haskell.

                                    f :: Int -> Int
                                    f x = do
                                      let y = x + 2
                                      let z = x * 2
                                      y + z
                                    
                                    1. 2

                                      Yes, you can have non-recursive let!

                                      test = runIdentity $ do
                                           (x,s) <- return $ foo 1 []
                                           (y,s) <- return $ bar x s
                                           (z,s) <- return $ baz x y s
                                           return (z,s)
                                      
                                      1. 2

                                        I don’t understand what the big deal is, we read from left to right not right to left. It’s just a notational convenience I really don’t understand how people could get so conservative that they can’t even handle a different direction of function composition. If you wrote right to left, I could see that being a serious inconvenience though.

                                  1. 27

                                    I was accepted to the Recurse Center and am arranging the logistics of moving to NYC from mid-September to mid-December. If anyone in NYC would like to meet up, message me. I plan to study category theory, dependent types, and, if I can find a study buddy, tools like Coq and TLA+.

                                    Codewise, I’m tinkering ahead on my current Haskell practice program, a solitaire solver. I’m also making demo Rails apps for my two factor authentication Rails gem.

                                    1. 4

                                      Check out @hwayne’s tutorial on learntla.com since it’s on a practical subset. Also, Alloy Analyzer has long been used to do something similar for structural analysis of programs with ease of use vs Coq etc.

                                      http://learntla.com/

                                      http://alloy.mit.edu/alloy/

                                      Hopefully, you master it all. TLA+ and Alloy just knock out lots of low-hanging fruit with relatively few people quiting due to difficulty like what happens with big-time provers.

                                      1. 3

                                        Great news, looking forward to the blog posts! Is there something similar to Recurse Center in Europe?

                                        1. 2

                                          There was “Hacker Retreat” in Berlin that was explicitly inspired by Recurse Center, but it disappeared in October or November 2015. I’m not aware of others, but I haven’t looked.

                                        2. 3

                                          Glad to have more RC people here. Enjoy!

                                          1. 2

                                            This is wonderful news! Looking forward to hearing all about it :).

                                            1. 2

                                              Congrats again, we’re looking forward to having you :)

                                            1. 4

                                              Tickets are completely fungible—you can buy fractional tickets.

                                              I don’t think that’s what fungible means. Fungible means exchangeable with another item of the same type. So grain is fungible because you don’t care which ton of grain you get but a house is not.

                                              There’s no explanation on what T_ohshit is.

                                              1. 2

                                                There’s no explanation on what T_ohshit is.

                                                I’d mentioned that in the “A worldwide casino” section, though it wasn’t called out super well:

                                                At some time T_ohshit, P_ticket will begin plummeting.

                                                I’m sorry if that wasn’t well highlighted though!

                                                Fungible means exchangeable with another item of the same type.

                                                In my readings this is true, but the additional implication is that, say, ten tenth-ton parcels of grain are as valuable as one ton of grain.

                                                If there is a better term for the property of money where it is subdividable, I’d be grateful to hear it!

                                                1. 1

                                                  Infinitely divisible?

                                                  1. 1

                                                    Continuous? Rather than discrete.

                                                    1. 1

                                                      but the additional implication is that, say, ten tenth-ton parcels of grain are as valuable as one ton of grain.

                                                      well something is fungible but not divisible.

                                                      a new iphone for example. You don’t really care which one you get but definitely do not want 2 halves.

                                                  1. 4

                                                    This ties back nicely to ‘Lazy Functional State Threads’ which recommends implementing references as an array of one element.