wip
This commit is contained in:
		
							
								
								
									
										71
									
								
								posts/configs.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								posts/configs.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					title: Extensible configuration Pt. 1
 | 
				
			||||||
 | 
					date: 2019-03-27
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is the first part of a series where I'm going through how to make
 | 
				
			||||||
 | 
					extensible configuration. There is nothing groundbreaking or new in this
 | 
				
			||||||
 | 
					series, it's just me going through different implementations and trying to
 | 
				
			||||||
 | 
					understand them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The source material for this post is [the fixed point implementation](https://github.com/NixOS/nixpkgs/blob/master/lib/fixed-points.nix) for nix.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By extensible configuration, I'm talking about nix style extensible
 | 
				
			||||||
 | 
					configuration, like overlays, overrides and extensions. Let's see an example of
 | 
				
			||||||
 | 
					an extensible configuration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``` nix
 | 
				
			||||||
 | 
					{ haskellPackages, fetchFromGitHub }:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let
 | 
				
			||||||
 | 
					  purescript = fetchFromGitHub {
 | 
				
			||||||
 | 
					    owner = "purescript";
 | 
				
			||||||
 | 
					    repo = "purescript";
 | 
				
			||||||
 | 
					    rev = "2cb4a6496052db726e099539be682b87585af494";
 | 
				
			||||||
 | 
					    sha256 = "1v4gs08xnqgym6jj3drkzbic7ln3hfmflpbpij3qzwxsmqd2abr7";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  hp = haskellPackages.extend (self: super: {
 | 
				
			||||||
 | 
					    purescript = super.callCabal2nix "purescript" purescript {};
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					hp.purescript;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					On a high level we are augmenting the `haskellPackages` attrset by replacing
 | 
				
			||||||
 | 
					the existing purescript package with a different one. The extension is a
 | 
				
			||||||
 | 
					function that takes two arguments, `self` and `super`. `super` is the original
 | 
				
			||||||
 | 
					non-lazy value and `self` is the lazy value that corresponds to the value at
 | 
				
			||||||
 | 
					end.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The first step on this journey is done by getting to know `fix`. Fix is
 | 
				
			||||||
 | 
					described being the least fixed point of a function. In practice it's a
 | 
				
			||||||
 | 
					function allowing declaring recursive functions without explicit recursion.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``` nix
 | 
				
			||||||
 | 
					fix = f: let x = f x; in x
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With fix you can have access to the lazy `self` value. It's value is whatever
 | 
				
			||||||
 | 
					would have been computed in the end. As it is lazy, it is possible to end up in
 | 
				
			||||||
 | 
					a recursive loop if there is a cyclic dependency.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``` nix
 | 
				
			||||||
 | 
					let recursive = fix (self: {
 | 
				
			||||||
 | 
					  foo = 3;
 | 
				
			||||||
 | 
					  bar = self.foo + 1;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					infinite = fix (self: {
 | 
				
			||||||
 | 
					  foo = self.bar + 1;
 | 
				
			||||||
 | 
					  bar = self.foo + 1;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can try those yourself. The first version is fine and returns an attrset
 | 
				
			||||||
 | 
					like you would expect. The second one has a cyclic dependency and nix helpfully
 | 
				
			||||||
 | 
					errors out.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- https://elvishjerricco.github.io/2017/04/01/nix-style-configs-in-haskell.html
 | 
				
			||||||
 | 
					- https://github.com/NixOS/nixpkgs/blob/master/lib/fixed-points.nix
 | 
				
			||||||
 | 
					- https://chshersh.github.io/posts/2019-03-25-comonadic-builders
 | 
				
			||||||
		Reference in New Issue
	
	Block a user