← Back to context

Comment by danieldk

4 days ago

My impression is that you can't really build nix as a DSL in haskell, because the core insight of nix is to introduce the "derivation" function into a pure programming language, whose behaviour is pure (the output is determined by only the inputs), but whose implementation is very much not (it builds packages from a specification).

Evaluation is completely pure (at least with flakes, which disallows querying environment variables, etc.). Evaluation of derivations will result in .drv files in the store, but that does not add impurity to the language itself. Building the .drv is a separate step (instantiation).

You could totally write something that generates .drv files in a different language and use Nix for instantiation (building). If I am not mistaken, this is how Guix started - they evaluated derivations defined in scheme to .drv files and then let the Nix daemon build them.

Aside from that, as a Nix user, I am happy that Haskell is not the language. Nix is a very small, simple language that is easy to wrap your head around and does not lead to a lot of abstractionitis. A want to say this in a way without painting a caricature, but the Haskell community has a tendency to pile on a lot of abstractions and I would hate to see a Nix with monad transformers, lenses, or whatever is popular these days.

> Evaluation is completely pure (at least with flakes, which disallows querying environment variables, etc.). Evaluation of derivations will result in .drv files in the store, but that does not add impurity to the language itself. Building the .drv is a separate step (instantiation).

If import-from-derivation is enabled (it normally is, it's a very useful feature, and the foundation of flakes), then some derivations need to be built to complete the evaluation.

https://nix.dev/manual/nix/2.25/language/import-from-derivat...

Even then functions like "readFile" are considered to be pure in nix, but not in haskell.

> If I am not mistaken, this is how Guix started - they evaluated derivations defined in scheme to .drv files and then let the Nix daemon build them

IIRC it still works that way; there's no real reason to change. Scheme isn't purely functional though (and the guix programming model is clearly imperative), so it doesn't have this mismatch.

  • If import-from-derivation is enabled

    I have never looked at the implementation of IFD, but I assume that the evaluation and instantiation are still separated (and Nix will do multiple passes).

    Even then functions like "readFile" are considered to be pure in nix, but not in haskell.

    I am pretty sure that, unless you use --impure, all files that are read are required to be in the store. Since the store is read-only, it does not break purity.

    At any rate, I agree that there will be some hoops to jump through. But I think it would be possible to make a Haskell DSL to define derivations similar to Nix. But I don't know why one would want to.

    • > I am pretty sure that, unless you use --impure, all files that are read are required to be in the store. Since the store is read-only, it does not break purity.

      Right, but even then the logical type for readFile would be something like "string -> string" (because from nix's perspective it is pure), but in haskell it would have to be "string -> IO string" (because from haskell's perspective it is not).

      Maybe this is fine, i just suspect it would make things messier than expected.

      Alternatively this could be worked around using unsafePerformIO or the FFI, but that feels a bit far away from the idea of just making a DSL? Unclear...

      > But I don't know why one would want to.

      Same, I just think it's an interesting discussion.