packages feed

cabal-fix-0.1.0.0: readme.md

# Table of Contents

1.  [cabal-fix](#orgbfbcd8c)
2.  [App Usage](#org2f4aafb)
3.  [App Configuration](#orga921360)
4.  [Library Usage](#orgbb0e777)
5.  [cabal init](#orge6fca8d)
    1.  [minimal](#orgc14dafe)
    2.  [code example](#orgd8c294c)
    3.  [simple](#org2493565)
6.  [Archive Exploration](#org733a366)
    1.  [imports](#org69e0aa6)
    2.  [tar file to list of cabal files](#org241dfdb)
        1.  [entries](#orgdc43fe9)
        2.  [Maximum file size:](#org39c1923)
        3.  [zero size](#orgcf21c34)
        4.  [preferred-versions](#orgb39b7ed)
        5.  [package.json](#org9b4f148)
        6.  [cabal files](#orge4acb82)
    3.  [latestCabals to CabalFields map](#org9ce30f8)
    4.  [CabalFields map to dependency graph](#orgb4f4cbb)
    5.  [algebraic-graphs](#org6f1757a)
    6.  [sections](#orgd2876cc)
        1.  [section count](#org39f7aed)
        2.  [section types](#orge952475)
        3.  [section in section](#org74c0b33)
        4.  [zero-section cfs](#orgd5e491e)
    7.  [Dependency counts](#org9a284e6)
    8.  [version ranges](#org198f27d)
        1.  [all versions are unique?](#org0b08b16)
        2.  [Version counts](#org39af952)
7.  [Field re-ordering](#org9771b7b)
8.  [references](#org15314af)


<a id="orgbfbcd8c"></a>

# cabal-fix

[![img](https://img.shields.io/hackage/v/cabal-fix.svg)](https://hackage.haskell.org/package/cabal-fix)
[![img](https://github.com/tonyday567/cabal-fix/workflows/haskell-ci/badge.svg)](https://github.com/tonyday567/cabal-fix/actions?query=workflow%3Ahaskell-ci)

`cabal-fix` helps fix your cabal files. This package:

-   Contains an app which parses your existing cabal file, re-renders it according to some config, then either displays a diff or alters your cabal file, in-place.
-   Is an idempotent parser of a cabal file or ByteString, into the `Field` type used in Cabal.
-   Is an inexact printer.
-   Contains code to explore the cabal index archive at the base of your cabal installation.


<a id="org2f4aafb"></a>

# App Usage

    
    #+end_export
    cabal-fix --help

    fixes your cabal file
    
    Usage: cabal-fix COMMAND [-d|--directory ARG] [-c|--config ARG]
    
      cabal fixer
    
    Available options:
      -d,--directory ARG       project directory
      -c,--config ARG          config file
      -h,--help                Show this help text
    
    Available commands:
      inplace                  fix cabal file inplace
      check                    check cabal file
      genConfig                generate config file


<a id="orga921360"></a>

# App Configuration

The configuration of cabal-fix is encapsulated in the Config type. The configuration file generated by the app (via `cabal-fix genConfig`) just (pretty) prints defaultConfig.

    import Text.Pretty.Simple
    pPrint defaultConfig

    Config
        { freeTexts = [ "description" ]
        , fieldRemovals = []
        , preferredDeps =
            [
                ( "base"
                , ">=4.7 && <5"
                )
            ]
        , addFields = []
        , fixCommas =
            [
                ( "extra-doc-files"
                , NoCommas
                )
            ,
                ( "build-depends"
                , PrefixCommas
                )
            ]
        , sortFieldLines =
            [ "build-depends"
            , "exposed-modules"
            , "default-extensions"
            , "ghc-options"
            , "extra-doc-files"
            , "tested-with"
            ]
        , sortFields = True
        , fieldOrdering =
            [
                ( "cabal-version"
                , 0.0
                )
            ,
                ( "import"
                , 1.0
                )
            ,
                ( "main-is"
                , 2.0
                )
            ,
                ( "default-language"
                , 3.0
                )
            ,
                ( "name"
                , 4.0
                )
            ,
                ( "hs-source-dirs"
                , 5.0
                )
            ,
                ( "version"
                , 6.0
                )
            ,
                ( "build-depends"
                , 7.0
                )
            ,
                ( "exposed-modules"
                , 8.0
                )
            ,
                ( "license"
                , 9.0
                )
            ,
                ( "license-file"
                , 10.0
                )
            ,
                ( "other-modules"
                , 11.0
                )
            ,
                ( "copyright"
                , 12.0
                )
            ,
                ( "category"
                , 13.0
                )
            ,
                ( "author"
                , 14.0
                )
            ,
                ( "default-extensions"
                , 15.0
                )
            ,
                ( "ghc-options"
                , 16.0
                )
            ,
                ( "maintainer"
                , 17.0
                )
            ,
                ( "homepage"
                , 18.0
                )
            ,
                ( "bug-reports"
                , 19.0
                )
            ,
                ( "synopsis"
                , 20.0
                )
            ,
                ( "description"
                , 21.0
                )
            ,
                ( "build-type"
                , 22.0
                )
            ,
                ( "tested-with"
                , 23.0
                )
            ,
                ( "extra-doc-files"
                , 24.0
                )
            ,
                ( "source-repository"
                , 25.0
                )
            ,
                ( "type"
                , 26.0
                )
            ,
                ( "common"
                , 27.0
                )
            ,
                ( "location"
                , 28.0
                )
            ,
                ( "library"
                , 29.0
                )
            ,
                ( "executable"
                , 30.0
                )
            ,
                ( "test-suite"
                , 31.0
                )
            ]
        , fixBuildDeps = True
        , depAlignment = DepAligned
        , removeBlankFields = True
        , valueAligned = ValueUnaligned
        , sectionMargin = Margin
        , commentMargin = NoMargin
        , narrowN = 60
        , indentN = 4
        }


<a id="orgbb0e777"></a>

# Library Usage

    :set -XOverloadedStrings
    :set -XOverloadedLabels
    :set -Wno-incomplete-uni-patterns
    :set -Wno-name-shadowing
    import CabalFix
    import Optics.Extra
    import Data.ByteString.Char8 qualified as C
    bs = minimalExampleBS
    cfg = defaultConfig
    (Just cf) = preview (cabalFields' cfg) bs
    fs = cf & view (#fields % fieldList')

    Build profile: -w ghc-9.4.8 -O1
    In order, the following will be built (use -v for more details):
     - cabal-fix-0.0.0.1 (lib) (ephemeral targets)
    Preprocessing library for cabal-fix-0.0.0.1..
    GHCi, version 9.4.8: https://www.haskell.org/ghc/  :? for help
    [1 of 4] Compiling CabalFix.FlatParse ( src/CabalFix/FlatParse.hs, interpreted )
    [2 of 4] Compiling CabalFix         ( src/CabalFix.hs, interpreted )
    [3 of 4] Compiling CabalFix.Archive ( src/CabalFix/Archive.hs, interpreted )
    [4 of 4] Compiling CabalFix.Patch   ( src/CabalFix/Patch.hs, interpreted )
    Ok, four modules loaded.

    cf & review (cabalFields' cfg) & C.putStr

    cabal-version: 3.0
    name: minimal
    version: 0.1.0.0
    license: BSD-2-Clause
    license-file: LICENSE
    build-type: Simple
    extra-doc-files: CHANGELOG.md
    
    common warnings
        ghc-options: -Wall
    
    library
        import: warnings
        exposed-modules: MyLib
        build-depends: base ^>=4.17.2.1
        hs-source-dirs: src
        default-language: GHC2021
    
    test-suite minimal-test
        import: warnings
        default-language: GHC2021
        type: exitcode-stdio-1.0
        hs-source-dirs: test
        main-is: Main.hs
        build-depends:
            base ^>=4.17.2.1,
            minimal


<a id="orge6fca8d"></a>

# cabal init


<a id="orgc14dafe"></a>

## minimal

A minimal `cabal init`

    mkdir minimal && cd minimal && cabal init --minimal --simple --overwrite --lib --tests --language=GHC2021 --license=BSD-2-Clause  -p minimal

    [Log] Using cabal specification: 3.0
    [Log] Creating fresh file LICENSE...
    [Log] Creating fresh file CHANGELOG.md...
    [Log] Creating fresh directory ./src...
    [Log] Creating fresh file src/MyLib.hs...
    [Log] Creating fresh directory ./test...
    [Log] Creating fresh file test/Main.hs...
    [Log] Creating fresh file minimal.cabal...
    [Warning] No synopsis given. You should edit the .cabal file and add one.
    [Info] You may want to edit the .cabal file and add a Description field.

Compared with the original `cabal init` contents, `cabal-fix`:

-   widens the `base` range, in line with standard practice.
-   reorders the `test-suite` section fields, in line with the ordering of the `library` section ones.

    cabal-fix check -d "minimal" -c "other/minimal.config"

    Right (Just [
      -"    build-depends:    base ^>=4.17.2.1",
      +"    build-depends:    base >=4.14 && <5",
      -"    default-language: GHC2021",
      +"    main-is:          Main.hs",
      -"    type:             exitcode-stdio-1.0",
      +"    build-depends:",
      -"    hs-source-dirs:   test",
      +"        base    >=4.14 && <5,",
      -"    main-is:          Main.hs",
      +"        minimal",
      -"    build-depends:",
      +"    hs-source-dirs:   test",
      -"        base ^>=4.17.2.1,",
      +"    default-language: GHC2021",
      -"        minimal",
      +"    type:             exitcode-stdio-1.0"])


<a id="orgd8c294c"></a>

## code example

For reference, the code below should produce the same results as the app run above:

    :set -XOverloadedStrings
    :set -XOverloadedLabels
    :set -Wno-incomplete-uni-patterns
    :set -Wno-name-shadowing
    :set -Wno-type-defaults
    import CabalFix
    import Text.Pretty.Simple
    import CabalFix.Patch
    import Data.TreeDiff
    bs = minimalExampleBS
    cfg = minimalConfig
    (Just cf) = preview (cabalFields' cfg) bs
    bs' = review (cabalFields' cfg) cf
    (Just cf') = preview (cabalFields' cfg) bs'
    cfFixed = fixCabalFields cfg cf
    bsFixed = review (cabalFields' cfg) cfFixed
    fmap ansiWlBgEditExpr $ patch (C.lines bs) (C.lines bsFixed)

    Just [
      -"    build-depends:    base ^>=4.17.2.1",
      +"    build-depends:    base >=4.14 && <5",
      -"    default-language: GHC2021",
      +"    main-is:          Main.hs",
      -"    type:             exitcode-stdio-1.0",
      +"    build-depends:",
      -"    hs-source-dirs:   test",
      +"        base    >=4.14 && <5,",
      -"    main-is:          Main.hs",
      +"        minimal",
      -"    build-depends:",
      +"    hs-source-dirs:   test",
      -"        base ^>=4.17.2.1,",
      +"    default-language: GHC2021",
      -"        minimal",
      +"    type:             exitcode-stdio-1.0"]


<a id="org2493565"></a>

## simple

    mkdir simple && cd simple && cabal init --simple --overwrite --lib --tests --language=GHC2021 --license=BSD-2-Clause  -p simple

    [Log] Using cabal specification: 3.0
    [Log] Creating fresh file LICENSE...
    [Log] Creating fresh file CHANGELOG.md...
    [Log] Creating fresh directory ./src...
    [Log] Creating fresh file src/MyLib.hs...
    [Log] Creating fresh directory ./test...
    [Log] Creating fresh file test/Main.hs...
    [Log] Creating fresh file simple.cabal...
    [Warning] No synopsis given. You should edit the .cabal file and add one.
    [Info] You may want to edit the .cabal file and add a Description field.

    cabal-fix check -d "simple" -c "other/minimal.config"

    Right (Just [
      +"cabal-version:   3.0",
      -"cabal-version:      3.0",
      +"",
      -"name:               simple",
      +"name:            simple",
      -"version:            0.1.0.0",
      +"version:         0.1.0.0",
      -"license:            BSD-2-Clause",
      +"license:         BSD-2-Clause",
      -"license-file:       LICENSE",
      +"license-file:    LICENSE",
      -"build-type:         Simple",
      +"build-type:      Simple",
      -"extra-doc-files:    CHANGELOG.md",
      +"extra-doc-files: CHANGELOG.md",
      -"    build-depends:    base ^>=4.17.2.1",
      +"    build-depends:    base >=4.14 && <5",
      -"    -- Base language which the package is written in.",
      +"    -- The entrypoint to the test suite.",
      -"    default-language: GHC2021",
      +"    main-is:          Main.hs",
      -"    -- Modules included in this executable, other than Main.",
      -"    -- other-modules:",
      +"    -- Test dependencies.",
      -"",
      +"    build-depends:",
      -"    -- LANGUAGE extensions used by modules in this package.",
      +"        base   >=4.14 && <5,",
      -"    -- other-extensions:",
      +"        simple",
      -"    -- The interface type and version of the test suite.",
      +"    -- Directories containing source files.",
      -"    type:             exitcode-stdio-1.0",
      +"    hs-source-dirs:   test",
      -"    -- Directories containing source files.",
      +"    -- Base language which the package is written in.",
      -"    hs-source-dirs:   test",
      +"    default-language: GHC2021",
      -"    -- The entrypoint to the test suite.",
      +"    -- Modules included in this executable, other than Main.",
      -"    main-is:          Main.hs",
      +"    -- other-modules:",
      +"    -- LANGUAGE extensions used by modules in this package.",
      -"    -- Test dependencies.",
      +"    -- other-extensions:",
      -"    build-depends:",
      +"",
      -"        base ^>=4.17.2.1,",
      +"    -- The interface type and version of the test suite.",
      -"        simple",
      +"    type:             exitcode-stdio-1.0"])


<a id="org733a366"></a>

# Archive Exploration

CabalFix.Archive contains functions to extract and explore cabal files listed in your cabal index file.

The sections below are some exploration notes.


<a id="org69e0aa6"></a>

## imports

    :r
    :set -Wno-type-defaults
    :set -Wno-name-shadowing
    :set -XOverloadedLabels
    :set -XOverloadedStrings
    :set -Wno-incomplete-uni-patterns
    import Algebra.Graph
    import Algebra.Graph.ToGraph qualified as ToGraph
    import CabalFix
    import CabalFix.Archive
    import CabalFix.FlatParse
    import Codec.Archive.Tar qualified as Tar
    import Control.Monad
    import Data.Bifunctor
    import Data.ByteString (ByteString)
    import Data.ByteString qualified as BS
    import Data.ByteString.Char8 qualified as C
    import Data.ByteString.Lazy qualified as BSL
    import Data.Char
    import Data.Either
    import Data.Function
    import Data.List qualified as List
    import Data.Map.Strict qualified as Map
    import Data.Ord
    import Data.Set qualified as Set
    import DotParse
    import FlatParse.Basic qualified as FP
    import System.Directory
    import Text.Pretty.Simple

    Ok, four modules loaded.


<a id="org241dfdb"></a>

## tar file to list of cabal files


<a id="orgdc43fe9"></a>

### entries

    es <- cabalEntries
    length es

    317368

    Tar.entryPath <$> take 5 es

    ["iconv/0.2/iconv.cabal","Crypto/3.0.3/Crypto.cabal","HDBC/1.0.1/HDBC.cabal","HDBC-odbc/1.0.1.0/HDBC-odbc.cabal","HDBC-postgresql/1.0.1.0/HDBC-postgresql.cabal"]

They are all normal files

    (length [x | (Tar.NormalFile x _) <- Tar.entryContent <$> es])

    317368


<a id="org39c1923"></a>

### Maximum file size:

    (\xs -> filter ((maximum (snd <$> xs) ==) . snd) xs) $ [(fp,x) | (fp, Tar.NormalFile _ x) <- (\e -> (Tar.entryPath e, Tar.entryContent e)) <$> es]

    [("acme-everything/2018.11.18/acme-everything.cabal",261865)]


<a id="orgcf21c34"></a>

### zero size

    take 4 $ (\xs -> filter ((0 ==) . snd) xs) $ [(fp,x) | (fp, Tar.NormalFile _ x) <- (\e -> (Tar.entryPath e, Tar.entryContent e)) <$> es]

    [("lzma/preferred-versions",0),("signal/preferred-versions",0),("peyotls-codec/preferred-versions",0),("th-orphans/preferred-versions",0)]


<a id="orgb39b7ed"></a>

### preferred-versions

[Cabal: preferred and deprecated versions | Hackage](https://hackage.haskell.org/package/Cabal/preferred)

    take 3 $ (\xs -> filter ((List.isSuffixOf "preferred-versions") . fst) xs) $ [(fp,bs) | (fp, Tar.NormalFile bs _) <- (\e -> (Tar.entryPath e, Tar.entryContent e)) <$> es]

    [("ADPfusion/preferred-versions","ADPfusion <0.4.0.0 || >0.4.0.0"),("AesonBson/preferred-versions","AesonBson <0.2.0 || >0.2.0 && <0.2.1 || >0.2.1"),("BiobaseXNA/preferred-versions","BiobaseXNA <0.9.1.0 || >0.9.1.0")]

    length $ (\xs -> filter ((List.isSuffixOf "preferred-versions") . fst) xs) $ [(fp,bs) | (fp, Tar.NormalFile bs _) <- (\e -> (Tar.entryPath e, Tar.entryContent e)) <$> es]

    3376


<a id="org9b4f148"></a>

### package.json

`package-json` content is a security/signing feature you can read about in [hackage-security](https://github.com/haskell-ng/hackage-security/blob/master/README.md).

    length $ filter ((== "package.json") . filenameFN . runParser_ filenameP . FP.strToUtf8 . fst) $ filter (not . (List.isSuffixOf "preferred-versions") . fst) $ [(fp,bs) | (fp, Tar.NormalFile bs _) <- (\e -> (Tar.entryPath e, Tar.entryContent e)) <$> es]

    137524


<a id="orge4acb82"></a>

### cabal files

Unique package/version combinations.

There are multiple versions of package/versions because of revisions. See [revisions-information.md](https://github.com/haskell-infra/hackage-trustees/blob/master/revisions-information.md)

Unique `*/*.cabal/version` entries

    cs <- cabals
    length cs

    137524

Unique cabal packages

    lcs <- latestCabals
    Map.size lcs

    17631

Average number of versions per package

    (fromIntegral (length cs)) / fromIntegral (Map.size lcs)

    7.800124780216664


<a id="org9ce30f8"></a>

## latestCabals to CabalFields map

    lcs <- latestCabals defaultConfig
    Map.size lcs
    cfg = defaultConfig
    lcs' = fmap (second (parseCabalFields cfg)) lcs
    Map.size $ Map.filter (snd >>> isLeft) lcs'
    :t lcs'
    badParse = Map.filter (isLeft . parseCabalFields cfg . snd) lcs
    Map.size badParse

    17631
    6
    lcs' :: Map.Map ByteString (Version, Either ByteString CabalFields)
    6


<a id="orgb4f4cbb"></a>

## CabalFields map to dependency graph

    lcfs <- latestCabalFields
    vlds = validLibDeps $ fmap snd lcfs
    Map.size vlds
    depG = allDepGraph $ fmap snd lcfs
    vertexCount depG
    edgeCount depG

    15547
    15621
    107566


<a id="org6f1757a"></a>

## algebraic-graphs

An (algebraic) graph of dependencies:

`text` package dependency example

    supers = upstreams "text" depG <> Set.singleton "text"
    superG = induce (`elem` (Data.Foldable.toList supers)) depG

    supers

    fromList ["array","binary","bytestring","deepseq","ghc-prim","template-haskell","text"]

    baseGraph = defaultGraph & attL GraphType (ID "size") .~ Just (IDQuoted "5!") & attL NodeType (ID "shape") .~ Just (ID "box") & attL NodeType (ID "height") .~ Just (ID 2) & gattL (ID "rankdir") .~ Just (IDQuoted "TB")
    g = toDotGraphWith Directed baseGraph superG
    processDotWith Directed ["-Tsvg", "-oother/textdeps.svg"] (dotPrint defaultDotConfig g)
    BS.writeFile "other/textdeps.dot" (dotPrint defaultDotConfig g)

![img](other/textdeps.svg)


<a id="orgd2876cc"></a>

## sections


<a id="org39f7aed"></a>

### section count

    cfs = lcfs & Map.toList & fmap (snd . snd)
    cfs & toListOf (each % #fields % fieldList') & fmap (filter isSection >>> length) & count_

    fromList [(0,359),(1,2559),(2,5508),(3,4730),(4,2224),(5,956),(6,479),(7,236),(8,138),(9,98),(10,63),(11,57),(12,31),(13,32),(14,22),(15,16),(16,12),(17,7),(18,11),(19,8),(20,8),(21,8),(22,4),(23,3),(24,7),(25,4),(26,6),(27,1),(28,1),(29,4),(30,2),(32,4),(33,2),(34,4),(36,1),(37,4),(38,1),(39,2),(40,1),(41,1),(43,2),(47,2),(48,2),(50,1),(65,1),(93,1),(97,1),(295,1)]


<a id="orge952475"></a>

### section types

    cfs & toListOf (each % #fields % fieldList') & fmap (filter isSection) & fmap (fmap (view fieldName')) & mconcat & count_ & Map.toList & List.sortOn (Down . snd)

    [("library",16028),("source-repository",13889),("test-suite",8718),("executable",7292),("flag",4134),("common",2302),("benchmark",1246),("custom-setup",321),("foreign-library",4)]

combinations:

    cfs & toListOf (each % #fields % fieldList') & fmap (filter isSection) & fmap (fmap (view fieldName')) & fmap (filter (not . (flip List.elem) ["source-repository", "custom-setup", "foreign-library", "flag", "common"])) & fmap (count_ >>> Map.toList >>> List.sortOn fst) & count_ & Map.toList & List.sortOn (Down . snd) & take 10

    [([("library",1)],7291),([("library",1),("test-suite",1)],4195),([("executable",1),("library",1)],1148),([("executable",1)],1105),([("executable",1),("library",1),("test-suite",1)],901),([("benchmark",1),("library",1),("test-suite",1)],520),([("library",1),("test-suite",2)],416),([],359),([("executable",2),("library",1)],163),([("executable",2),("library",1),("test-suite",1)],133)]

at least 1 combinations:

    cfs & toListOf (each % #fields % fieldList') & fmap (filter isSection) & fmap (fmap (view fieldName')) & fmap (filter (not . (flip List.elem) ["source-repository", "custom-setup", "foreign-library", "flag", "common"])) & fmap (count_ >>> Map.toList >>> fmap fst >>> List.sortOn id) & count_ & Map.toList & List.sortOn (Down . snd) & take 10

    [(["library"],7297),(["library","test-suite"],4778),(["executable","library"],1490),(["executable","library","test-suite"],1309),(["executable"],1263),(["benchmark","library","test-suite"],739),([],359),(["benchmark","executable","library","test-suite"],182),(["executable","test-suite"],119),(["benchmark","library"],59)]


<a id="org74c0b33"></a>

### section in section

    sections' = to (filter isSection)
    -- cfs & fmap (foldOf (#fields % fieldList' % sections' % each % secFields' % sections')) & filter (not . null) & fmap (second (fmap (view fieldName'))) & fmap snd & mconcat & count_
    cfs & fmap (foldOf (#fields % fieldList' % sections' % each % secFields' % sections')) & filter (not . null) & fmap ((fmap (view fieldName'))) & mconcat & count_

    fromList [("elif",52),("else",3203),("if",11459),("library",3)]

Embedded libraries are all deprecated.


<a id="orgd5e491e"></a>

### zero-section cfs

Looks like library fields used to be allowed at the top level&#x2026;

    cfs0 = cfs & toListOf (each % #fields % fieldList') & filter ((==0) . length . (filter isSection))
    length cfs0
    count_ $ cfs0 & fmap (foldOf (field' "build-depends") >>> length)
    cfs00 = cfs0 & filter (foldOf (field' "build-depends") >>> length >>> (==0))
    length cfs00

    359
    fromList [(0,2),(1,349),(2,7),(4,1)]
    2


<a id="org9a284e6"></a>

## Dependency counts

package dependency count:

    lcfs & fmap (snd >>> libDeps >>> fmap dep >>> List.nub >>> length) & Map.toList & List.sortOn (Down . snd) & take 20

    [("acme-everything",7533),("yesod-platform",132),("planet-mitchell",109),("freckle-app",78),("cachix",76),("btc-lsp",71),("too-many-cells",70),("swarm",68),("ghcide",67),("pandoc",67),("sprinkles",65),("pantry-tmp",64),("taffybar",63),("NGLess",60),("project-m36",59),("stack",59),("espial",58),("hermes",58),("purescript",56),("futhark",55)]

dependency count:

    lcfs & fmap (snd >>> libDeps >>> fmap dep >>> List.nub) & Map.toList & fmap snd & mconcat & count_ & Map.toList & List.sortOn (snd >>> Down) & take 40

    [("base",14883),("bytestring",5384),("text",4972),("containers",4753),("mtl",3468),("transformers",3070),("aeson",2013),("time",1961),("vector",1793),("directory",1597),("filepath",1510),("template-haskell",1472),("unordered-containers",1392),("deepseq",1240),("lens",1173),("hashable",930),("binary",929),("array",892),("exceptions",855),("process",844),("stm",819),("random",811),("http-types",784),("attoparsec",781),("network",756),("parsec",744),("data-default",609),("QuickCheck",597),("conduit",503),("http-client",497),("split",472),("primitive",470),("ghc-prim",456),("async",449),("semigroups",427),("monad-control",424),("scientific",420),("resourcet",401),("unix",398),("utf8-string",392)]


<a id="org198f27d"></a>

## version ranges

    cs <- cabals
    length cs

    137323

    :t cs
    
    mVersions = Map.fromListWith (<>) $ ((\x -> (nameFN x, (:[]) $ (versionInts $ versionFN x))) . fst) <$> cs
    Map.size mVersions

    cs :: [(FileName, ByteString)]
    17631

    (Just x1) = Map.lookup "chart-svg" mVersions
    x1
    minimum x1
    maximum x1

    [[0,6,0,0],[0,5,2,0],[0,5,1,1],[0,5,1,0],[0,5,0,0],[0,4,1,1],[0,4,1,0],[0,4,0],[0,3,3],[0,3,2],[0,3,1],[0,3,0],[0,2,3],[0,2,2],[0,2,1],[0,2,0],[0,1,3],[0,1,2],[0,1,1],[0,1,0],[0,0,3],[0,0,2],[0,0,1]]
    [0,0,1]
    [0,6,0,0]


<a id="org0b08b16"></a>

### all versions are unique?

    take 10 $ Map.toList $ Map.filter (\a -> length a /= length (List.nub a)) mVersions

    []


<a id="org39af952"></a>

### Version counts

    take 10 $ List.sortOn (Down . snd) $ Map.toList $ Map.map length mVersions

    [("haskoin-store",298),("git-annex",282),("hlint",221),("yesod-core",216),("purescript",204),("warp",204),("pandoc",193),("hakyll",192),("egison",190),("persistent",186)]


<a id="org9771b7b"></a>

# Field re-ordering

    zipWith (\o l -> (fst l, o)) [0..] (List.sortOn snd $ fieldOrdering defaultConfig)

    [("cabal-version",0),("import",1),("main-is",2),("default-language",3),("name",4),("hs-source-dirs",5),("version",6),("build-depends",7),("exposed-modules",8),("license",9),("license-file",10),("other-modules",11),("copyright",12),("category",13),("author",14),("default-extensions",15),("ghc-options",16),("maintainer",17),("homepage",18),("bug-reports",19),("synopsis",20),("description",21),("build-type",22),("tested-with",23),("extra-doc-files",24),("source-repository",25),("type",26),("common",27),("location",28),("library",29),("executable",30),("test-suite",31)]


<a id="org15314af"></a>

# references

[Distribution.Fields.Field](https://hackage.haskell.org/package/Cabal-syntax-3.10.2.0/docs/Distribution-Fields-Field.html)

[optics-core: Optics as an abstract interface: core definitions](https://hackage.haskell.org/package/optics-core-0.4.1.1)

[6. Package Description — Cabal 3.10.1.0 User&rsquo;s Guide](https://cabal.readthedocs.io/en/stable/cabal-package.html#package-descriptions)