- Debian though a functional lens
- Joey Hess, DebConf14
Using Nix's functional package management as inspiration, let's look at Debian from a functional programming perspective.
- https://joeyh.name/talks/debconf-14-debian-through-a-functional-lens/
- Joey Hess, DebConf14
- a motivating example (haskell-dav)
- (picked because Clint is in the audience)
% wc -l debian/rules debian/control Network/Protocol/HTTP/DAV.hs DAV.cabal 8 debian/rules 126 debian/control 444 Network/Protocol/HTTP/DAV.hs 79 DAV.cabal
- Build-Depends: debhelper (>= 9)
, haskell-devscripts (>= 0.8.13) , cdbs , ghc , ghc-prof , ghc-ghci , libghc-case-insensitive-dev (>= 0.4) , libghc-case-insensitive-prof , libghc-either-dev (>= 4.1) , libghc-either-prof , libghc-errors-dev , libghc-errors-prof , libghc-http-client-dev (>= 0.2) , libghc-http-client-prof , libghc-http-client-tls-dev (>= 0.2) , libghc-http-client-tls-prof , libghc-http-types-dev (>= 0.7) , libghc-http-types-prof , libghc-lens-dev (>= 3.0) , libghc-lens-prof , libghc-lifted-base-dev (>= 0.1) , libghc-lifted-base-prof , libghc-monad-control-dev (>= 0.3.2) , libghc-monad-control-prof , libghc-mtl-dev (>= 2.1) , libghc-mtl-prof , libghc-network-dev (>= 2.3) , libghc-network-prof , libghc-optparse-applicative-dev (>= 0.5.0) , libghc-optparse-applicative-prof , libghc-transformers-dev (>= 0.3) , libghc-transformers-prof , libghc-transformers-base-dev , libghc-transformers-base-prof , libghc-utf8-string-dev , libghc-utf8-string-prof , libghc-xml-conduit-dev (>= 1.0) , libghc-xml-conduit-dev (<< 1.3) , libghc-xml-conduit-prof , libghc-xml-hamlet-dev (>= 0.4) , libghc-xml-hamlet-dev (<< 0.5) , libghc-xml-hamlet-prof
- Build-Depends-Indep: ghc-doc
, libghc-case-insensitive-doc , libghc-either-doc , libghc-errors-doc , libghc-http-client-doc , libghc-http-client-tls-doc , libghc-http-types-doc , libghc-lens-doc , libghc-lifted-base-doc , libghc-monad-control-doc , libghc-mtl-doc , libghc-network-doc , libghc-optparse-applicative-doc , libghc-transformers-doc , libghc-transformers-base-doc , libghc-utf8-string-doc , libghc-xml-conduit-doc , libghc-xml-hamlet-doc
- boilerplate (repeated 3 times in this package)
Package: libghc-dav-{dev,prof,doc} Architecture: any Depends: ${shlibs:Depends} , ${haskell:Depends} , ${misc:Depends} Recommends: ${haskell:Recommends} Suggests: ${haskell:Suggests} Provides: ${haskell:Provides} Description: ${haskell:ShortDescription}${haskell:ShortBlurb} ${haskell:LongDescription} . ${haskell:Blurb} - rudimentary control file refactoring
X-Description: RFC 4918 WebDAV support This is a library for the Web Distributed Authoring and Versioning (WebDAV) extensions to HTTP. At present it supports a very small subset of client functionality.
- massive redundancy and make-work
- Debian Haskell Group maintains 844+ of these
- Debian perl Group: 3327+!
- ... that's 20% of the source packages in Debian
- ... and there are more
- (picked because Clint is in the audience)
- nixos equivalent
- ... not exactly ideal, but a lot better
# This file was auto-generated by cabal2nix. Please do NOT edit manually! { cabal, caseInsensitive, either, errors, httpClient, httpClientTls , httpTypes, lens, liftedBase, monadControl, mtl, network , optparseApplicative, transformers, transformersBase, xmlConduit , xmlHamlet }: cabal.mkDerivation (self: { pname = "DAV"; version = "0.8"; sha256 = "0khjid5jaaf4c3xn9cbph8ay4ibqr7pg3b3w7d0kfvci90ksc08r"; isLibrary = true; isExecutable = true; buildDepends = [ caseInsensitive either errors httpClient httpClientTls httpTypes lens liftedBase monadControl mtl network optparseApplicative transformers transformersBase xmlConduit xmlHamlet ]; jailbreak = true; meta = { homepage = "http://floss.scru.org/hDAV"; description = "RFC 4918 WebDAV support"; license = self.stdenv.lib.licenses.gpl3; platforms = self.ghc.meta.platforms; }; }) - debian/control dream equivalent (take 1)
{ haskell_libraries } Section: web Standards-Version: 3.9.5Package: hdav Depends: { haskell_depends } Description: command-line WebDAV client hdav currently only supports copying a file and associated WebDAV properties from one URL to another. - debian/control dream equivalent (take 2)
-- valid haskell code this time source = haskell_source & section Web & standardsversion 3.9.5 packages = haskell_libraries `also` package "hdav" & depends haskell_depends & description "command-line WebDAV client" [ "hdav currently only supports copying a file and associated WebDAV" , "properties from one URL to another." ]
- comparing debian/control types
- control :: ControlFile -- current
- ♥ simple
- X redundant boilerplate
- X inflexible
- control :: IO Control -- executable control file
- ♥ avoids boilerplate
- ♥ no language lock-in
- X cannot extract Control data w/o running arbitrary code
- seems to completely rule this out!
- gencontrol :: IO ControlFie -- pre-generate control file
- ♥ already available
- see "debdry - Debian Don't Repeat Yourself"
- ♥ avoids boilerplate
- ♥ no language lock-in
- X "this file was auto-generated. Please do NOT edit manually"
- ♥ already available
- control :: UpstreamSource -> Control -- control file as functional code
- ♥ avoids boilerplate
- ♥ purely functional safety
- control file generates same output given same inputs
- result not based on /etc/lsb_release or phase of the moon
- X language lock-in
- but language lock-in has not been a problem for debian/rules ...
- control :: ControlFile -- current
- nixos exploration
- filesystem layout
- ldd $(which bash)
- which bash
- find /usr
- # explore /run/current-system and /nix briefly
- declarative package management
- man configuration.nix
- vim /etc/nixos/configuration.nix, make some changes
- nixos-rebuild switch
- generation based package management
- # as root or non-root (non-root updates ~/.nix)
- nix-env --install git-annex
- nix-env --list-generations
- nix-env --rollback
- filesystem layout
- functional runtime
- immutable data
- git commits
- docker images
- nix derivations
- copy on write
- git delta compression
- docker aufs layers
- nix generations
- garbage collection
- git gc
- docker images -f dangling=true # or something like that
- nix-env --delete-generations; nix-collect-garbage
Increasingly, the running OS is like the runtime of a functional program.
- immutable data
- a progression: IO to declarative to FP
- debian/rules
- manual -- IO (cp foo bar)
- debhelper -- IO, some declarative (debian/install etc)
- dh -- declarative, some IO (override_dh_auto_*)
- ... FP?
- many debhelper feature requests are now about the
- limits of declarative configuration
- "debian/install is too inflexible"
- maintainer scripts
- manual -- IO
- debhelper autoscripts -- sorta declarative, still lots of IO
- triggers -- some declarative, some IO
- ... FP?
- talked with Russ yesterday about eliminating
- more maintainer scripts, he suggested an EDSL
- to simplify debconf config scripts
- config files
- just a static file -- declarative (mostly)
- debconf generated file -- IO (oops!)
- file.d -- FP-ish (Set File -> File)
- debian/copyright (a bit of a stretch)
- prose
- "This package was downloaded in 1997 from sunsite
- and it is GPL licensed by ESR."
- structured
- Copyright: 2009-2013 J. Random Hacker
- License: GPL-3+
- almost programming
- "License: $foo with $bar exception"
- "License: $X or $Y, and $Z"
- prose
- OS configuration
- apt-get install -- IO
- puppet/etc -- declarative-ish + IO
- docker -- declarative-ish (dockerfile)
- nixos -- FP
- debian/rules