anchor.diff:      # packages themselves. Using nix-shell on this derivation will
       # give you an environment suitable for developing the listed
       # packages with an incremental tool like cabal-install.
  +    #
       # In addition to the "packages" arg and "withHoogle" arg, anything that
       # can be passed into stdenv.mkDerivation can be included in the input attrset
       #
  
positive.code:     #     (import ./.).shellFor {
      #       packages = p: [p.frontend p.backend p.common];
      #       withHoogle = true;
      #       buildInputs = [ pkgs.python ];
      #     }
      #
      #     -- cabal.project
  
negative.code:     #
      #     bash$ nix-shell --run "cabal new-build all"
      #     bash$ nix-shell --run "python"
      shellFor =
        { # Packages to create this development shell for.  These are usually
          # your local packages.
          packages
        , # Whether or not to generated a Hoogle database for all the
          # dependencies.
          withHoogle ? false
        , ...
        } @ args:
        let
          # A list of the packages we want to build a development shell for.
          #
          # This is a list of Haskell package derivations.
          selected = packages self;
  
          # This is a list of attribute sets, where the each attribute set
          # corresponds to the build inputs one of the packages input to shellFor.
          #
          # Each attribute has keys like buildDepends, executableHaskellDepends,
          # testPkgconfigDepends, etc.  The values for the keys of the attribute
          # set are lists of dependencies.
          #
          # Example:
          #   cabalDepsForSelected
          #   => [
          #        # This may be the attribute set corresponding to the `backend`
          #        # package in the example above.
          #        { buildDepends = [ gcc ... ];
          #          libraryHaskellDepends = [ lens conduit ... ];
          #          ...
          #        }
          #        # This may be the attribute set corresponding to the `common`
          #        # package in the example above.
          #        { testHaskellDepends = [ tasty hspec ... ];
          #          libraryHaskellDepends = [ lens aeson ];
          #          benchmarkHaskellDepends = [ criterion ... ];
          #          ...
          #        }
          #        ...
          #      ]
          cabalDepsForSelected = map (p: p.getCabalDeps) selected;
  
          # A predicate that takes a derivation as input, and tests whether it is
          # the same as any of the `selected` packages.
          #
          # Returns true if the input derivation is not in the list of `selected`
          # packages.
          #
          # isNotSelected :: Derivation -> Bool
          #
          # Example:
          #
          #   isNotSelected common [ frontend backend common ]
          #   => false
          #
          #   isNotSelected lens [ frontend backend common ]
          #   => true
          isNotSelected = input: pkgs.lib.all (p: input.outPath or null != p.outPath) selected;
  
          # A function that takes a list of list of derivations, filters out all
          # the `selected` packages from each list, and concats the results.
          #
          #   zipperCombinedPkgs :: [[Derivation]] -> [Derivation]
          #
          # Example:
          #   zipperCombinedPkgs [ [ lens conduit ] [ aeson frontend ] ]
          #   => [ lens conduit aeson ]
          #
          # Note: The reason this isn't just the function `pkgs.lib.concat` is
          # that we need to be careful to remove dependencies that are in the
          # `selected` packages.
          #
          # For instance, in the above example, if `common` is a dependency of
          # `backend`, then zipperCombinedPkgs needs to be careful to filter out
          # `common`, because cabal will end up ignoring that built version,
          # assuming new-style commands.
          zipperCombinedPkgs = vals:
            pkgs.lib.concatMap
              (drvList: pkgs.lib.filter isNotSelected drvList)
              vals;
  
          # Zip `cabalDepsForSelected` into a single attribute list, combining
          # the derivations in all the individual attributes.
          #
          # Example:
          #   packageInputs
          #   => # Assuming the value of cabalDepsForSelected is the same as
          #      # the example in cabalDepsForSelected:
          #      { buildDepends = [ gcc ... ];
          #        libraryHaskellDepends = [ lens conduit aeson ... ];
          #        testHaskellDepends = [ tasty hspec ... ];
          #        benchmarkHaskellDepends = [ criterion ... ];
          #        ...
          #      }
          #
          # See the Note in `zipperCombinedPkgs` for what gets filtered out from
          # each of these dependency lists.
          packageInputs =
            pkgs.lib.zipAttrsWith (_name: zipperCombinedPkgs) cabalDepsForSelected;
  
          # A attribute set to pass to `haskellPackages.mkDerivation`.
          #
          # The important thing to note here is that all the fields from
          # packageInputs are set correctly.
          genericBuilderArgs = {
            pname =
              if pkgs.lib.length selected == 1
              then (pkgs.lib.head selected).name
              else "packages";
            version = "0";
            license = null;
          }
          // packageInputs;
  
          # This is a pseudo Haskell package derivation that contains all the
          # dependencies for the packages in `selected`.
          #
          # This is a derivation created with `haskellPackages.mkDerivation`.
          #
          # pkgWithCombinedDeps :: HaskellDerivation
          pkgWithCombinedDeps = self.mkDerivation genericBuilderArgs;
  
          # The derivation returned from `envFunc` for `pkgWithCombinedDeps`.
          #
          # This is a derivation that can be run with `nix-shell`.  It provides a
          # GHC with a package database with all the dependencies of our
          # `selected` packages.
          #
          # This is a derivation created with `stdenv.mkDerivation` (not
          # `haskellPackages.mkDerivation`).
          #
          # pkgWithCombinedDepsDevDrv :: Derivation
          pkgWithCombinedDepsDevDrv = pkgWithCombinedDeps.envFunc { inherit withHoogle; };
  
          mkDerivationArgs = builtins.removeAttrs args [ "packages" "withHoogle" ];
  
        in pkgWithCombinedDepsDevDrv.overrideAttrs (old: mkDerivationArgs // {
          nativeBuildInputs = old.nativeBuildInputs ++ mkDerivationArgs.nativeBuildInputs or [];
          buildInputs = old.buildInputs ++ mkDerivationArgs.buildInputs or [];
        });
  