What’s Needed

To start using Hpack-Dhall we want a package.dhall file.

NotePackage Description Files

Hpack converts a package.yaml into a package-name.cabal. The Hpack package.yaml file and the Cabal .cabal file are both package description files as is a package.dhall file.

If you have nothing, then follow starting from scatch instructions. Either of the other formats can be used as the starting point for a translation to package.dhall;

Starting from Scratch

If you don’t yet have a package, these can be created with cabal init or stack new with arguments “project-name” or “project-name” and “template-name”, picking one of the Stack templates such as “simple-hpack”.

When the template used with stack new or the default template creates a single package project, the name of the project folder and the name of the package are the same. The default project file with Stack is stack.yaml.

Another option is copying someone else’s package description in package.dhall, package.yaml or .cabal format and modifying it for your purposes.

Starting from Cabal

If you already have a package description in .cabal format and still want to use Hpack-Dhall, you could either try to regenerate the .cabal file from a package.dhall file you construct by hand or you could try using hpack-convert to convert to a package.yaml and then follow the Starting from Hpack instructions.

Last published to Hackage in 2017, hpack-convert is a fork of sol/hpack. There are unmerged pull requests on yamadapc/hpack-convert, some of which mention getting it building again, and it doesn’t build with GHC versions, 8.2.* .. 9.14.*.

Starting from Hpack

CautionNo Package Type Definition

There’s no Hpack schema and we don’t provide a type for package.dhall.

If you already have a package.yaml, it should be pretty straightfoward to translate this to package.dhall. If your package.yaml is small, translation by hand is not too onerous. There’s also a tool for conversion, yaml-to-dhall, included in the dhall-yaml package. This can be installed with:

$ cabal install dhall-yaml --ignore-project

This tool has quite a few options:

$ yaml-to-dhall --help
Usage: yaml-to-dhall [type | [SCHEMA] [--records-strict | --records-loose]
                       [--no-keyval-arrays] [--no-keyval-maps]
                       [--unions-first | --unions-none | --unions-strict]
                       [--omissible-lists] [--file FILE] [--output FILE]
                       [--ascii] [--plain] |
                       (-V|--version)]

  Convert a YAML expression to a Dhall expression, given the expected Dhall type

Available options:
  -h,--help                Show this help text
  SCHEMA                   Dhall type expression (schema)
  --records-strict         Fail if any JSON fields are missing from the expected
                           Dhall type
  --records-loose          Tolerate JSON fields not present within the expected
                           Dhall type
  --no-keyval-arrays       Disable conversion of key-value arrays to records
  --no-keyval-maps         Disable conversion of homogeneous map objects to
                           association lists
  --unions-first           The first value with the matching type (successfully
                           parsed all the way down the tree) is accepted, even
                           if not the only possible match. (DEFAULT)
  --unions-none            Unions not allowed
  --unions-strict          Error if more than one union values match the type
                           (and parse successfully)
  --omissible-lists        Tolerate missing list values, they are assumed empty
  --file FILE              Read YAML expression from a file instead of standard
                           input
  --output FILE            Write Dhall expression to a file instead of standard
                           output
  --ascii                  Format code using only ASCII syntax
  --plain                  Disable syntax highlighting
  -V,--version             Display version

Available commands:
  type                     Output the inferred Dhall type from a YAML value

It can do the conversion and supply the type it infers, even with quite large package descriptions, such as Stack’s:

examples/stack/package-type.dhall
{ author : Text
, category : Text
, custom-setup : { dependencies : List Text }
, dependencies : List Text
, description : Text
, executables :
    { stack :
        { dependencies : List Text
        , generated-other-modules : List Text
        , ghc-options : List Text
        , main : Text
        , source-dirs : Text
        , when :
            List
              { condition : Text
              , cpp-options : Optional Text
              , dependencies : Optional (List Text)
              , ld-options : Optional (List Text)
              }
        }
    , stack-integration-test :
        { dependencies : List Text
        , ghc-options : List Text
        , main : Text
        , source-dirs : List Text
        , when :
            List
              { buildable : Optional Bool
              , condition : Text
              , ld-options : Optional (List Text)
              }
        }
    }
, extra-source-files : List Text
, flags :
    { developer-mode : { default : Bool, description : Text, manual : Bool }
    , disable-git-info : { default : Bool, description : Text, manual : Bool }
    , hide-dependency-versions :
        { default : Bool, description : Text, manual : Bool }
    , integration-tests : { default : Bool, description : Text, manual : Bool }
    , static : { default : Bool, description : Text, manual : Bool }
    , supported-build : { default : Bool, description : Text, manual : Bool }
    }
, ghc-options : List Text
, github : Text
, homepage : Text
, language : Text
, library :
    { exposed-modules : List Text
    , generated-exposed-modules : List Text
    , ghc-options : List Text
    , source-dirs : Text
    , when :
        List
          { condition : Text
          , `else` : { c-sources : Text, source-dirs : Text }
          , `then` : { source-dirs : Text }
          }
    }
, license : Text
, maintainer : Text
, name : Text
, spec-version : Text
, synopsis : Text
, tests :
    { stack-test :
        { dependencies : List Text
        , ghc-options : List Text
        , main : Text
        , source-dirs : Text
        , verbatim : Text
        , when :
            List
              { condition : Text
              , `else` : { source-dirs : Text }
              , `then` : { source-dirs : Text }
              }
        }
    }
, version : Text
, when :
    List
      { condition : Text
      , dependencies : Optional Text
      , `else` :
          Optional
            { cpp-options : Optional Text
            , dependencies : Optional (List Text)
            , verbatim : Optional Text
            }
      , `then` :
          Optional { cpp-options : Text, dependencies : Optional (List Text) }
      }
}
CautionLexical Field Order

If we reorder the fields of the inferred type and supply this as a SCHEMA to yaml-to-dhall, this has no effect on the resultant field order. Unfortunately, your desired field order must be imposed by hand after the conversion.

Without any configuration, the fields will be sorted lexically and that will likely not be what you want:

examples/stack/package.dhall
{ author = "Commercial Haskell SIG"
, category = "Development"
, description =
    ''
    Please see the documentation at <https://docs.haskellstack.org>
    for usage information.
    .
    If building a 'stack' executable for distribution, please download the
    source code from <https://github.com/commercialhaskell/stack/releases>
    and build it using Stack itself in order to ensure identical behaviour
    to official binaries. This package on Hackage is provided for convenience
    and bootstrapping purposes.
    .
    Note that the API for the library is not currently stable, and may
    change significantly, even between minor releases. It is
    currently only intended for use by the executable.
    ''
, github = "commercialhaskell/stack"
, homepage = "http://haskellstack.org"
, language = "GHC2021"
, license = "BSD3"
, maintainer = "manny@fpcomplete.com"
, name = "stack"
, spec-version = "0.35.0"
, synopsis = "The Haskell Tool Stack"
, version = "2.12.0"