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