Last active
March 17, 2022 22:07
-
-
Save danidiaz/f8c260755ea81ac365a40aba2ed8b802 to your computer and use it in GitHub Desktop.
Modeling Nix's "override" and "overrideAttrs" in Haskell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- | Derivations in Nixpkgs are usually the result of a chain of function calls. | |
| -- Typically, a function receives some input derivations as arguments (the "inputs | |
| -- pattern") and it eventually calls the 'mkDerivation' function, which produces the | |
| -- actual derivation value that is put into Nixpkgs. | |
| -- | |
| -- Turns out that derivation values in Nixpkgs keep a "memory" of how they were produced at | |
| -- those two stages: which functions were called, and with which arguments. They | |
| -- also provide "hooks" that allow re-running the stages with (partially or | |
| -- totally) different arguments, resulting in a new derivation. | |
| -- | |
| -- The good thing about these hooks is that you don't need to supply the full | |
| -- arguments to re-create the derivation, only the parts that you want changed. | |
| -- | |
| -- There are two hooks: | |
| -- | |
| -- - "override" for tweaking the call to the initial function which took the input derivations as arguments. | |
| -- | |
| -- - "overrideAttrs" for tweaking the call to mkDerivation. | |
| -- | |
| -- Here's an attempt at modeling something resembling that in Haskell. It doesn't aim to be a practical | |
| -- piece of code, just a tool for thought. | |
| module Main where | |
| import Data.Monoid | |
| type Traced m a = m -> a -- See Control.Comonad.Traced | |
| -- When a function has a Monoid input, it's easy to extract a result. | |
| extract :: Monoid m => Traced m a -> a | |
| extract f = f mempty | |
| -- We don't bother defining any fields. | |
| data Derivation = Derivation deriving (Show) | |
| newtype MkDerivationAttrs = MkDerivationAttrs {getMkDerivationAttrs :: String} | |
| -- Tweak the attributes with a function. | |
| type OverrideAttrs = Endo MkDerivationAttrs | |
| mkDerivation :: MkDerivationAttrs -> Traced OverrideAttrs Derivation | |
| mkDerivation attrs f = mkDerivation_ (appEndo f attrs) | |
| where | |
| mkDerivation_ :: MkDerivationAttrs -> Derivation | |
| mkDerivation_ = undefined -- whatever. Provided by the library. | |
| type Inputs = [Derivation] -- could be a map, or whatever | |
| -- Tweak the input derivations with a function. | |
| type Override = Endo Inputs | |
| -- This callPackage doesn't do the "select the packages from the whole of nixpkgs" thing, | |
| -- in only makes the inputs overrideable. | |
| callPackage :: | |
| (Inputs -> Traced x Derivation) -> | |
| (Inputs -> Traced (Override, x) Derivation) | |
| callPackage buildFromInputs inputs (override, overrideAttrs) = | |
| buildFromInputs (appEndo override inputs) overrideAttrs | |
| -- Example of derivation-building function provided by the library user. | |
| -- The library user only concerns itself with buiding the derivation, he | |
| -- should leave to 'callPackage' the task of making the inputs overrideable. | |
| someDerivationFromInputs :: Inputs -> Traced OverrideAttrs Derivation | |
| -- The implementation should make use of mkDerivation at the end. | |
| someDerivationFromInputs inputs endos = undefined | |
| main :: IO () | |
| main = do | |
| let someDerivationFromInputs' :: Inputs -> Traced (Override, OverrideAttrs) Derivation | |
| someDerivationFromInputs' = callPackage someDerivationFromInputs | |
| someInput :: Derivation | |
| someInput = Derivation | |
| anotherInput :: Derivation | |
| anotherInput = Derivation | |
| print $ extract $ someDerivationFromInputs' [someInput, anotherInput] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@danidiaz and here's my silly nix overlays in haskell from a few years ago :)
https://gist.github.com/pwm/7546391b230c7645ed278a5a2e7ed19e