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/
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
nixos equivalent
; # 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;
; };
; })
... not exactly ideal, but a lot better
debian/control dream equivalent (take 1)
; { haskell_libraries }
; Section: web
; Standards-Version: 3.9.5
;
; 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.
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"
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 ...
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
functional runtime
: Increasingly, the running OS is like the runtime
: of a functional program.
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
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"
OS configuration
apt-get install -- IO
puppet/etc -- declarative-ish + IO
docker -- declarative-ish (dockerfile)
nixos -- FP